OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 // and store it in a LanguageMode variable with the given name. | 132 // and store it in a LanguageMode variable with the given name. |
133 #define CONVERT_LANGUAGE_MODE_ARG(name, index) \ | 133 #define CONVERT_LANGUAGE_MODE_ARG(name, index) \ |
134 ASSERT(args[index]->IsSmi()); \ | 134 ASSERT(args[index]->IsSmi()); \ |
135 ASSERT(args.smi_at(index) == CLASSIC_MODE || \ | 135 ASSERT(args.smi_at(index) == CLASSIC_MODE || \ |
136 args.smi_at(index) == STRICT_MODE || \ | 136 args.smi_at(index) == STRICT_MODE || \ |
137 args.smi_at(index) == EXTENDED_MODE); \ | 137 args.smi_at(index) == EXTENDED_MODE); \ |
138 LanguageMode name = \ | 138 LanguageMode name = \ |
139 static_cast<LanguageMode>(args.smi_at(index)); | 139 static_cast<LanguageMode>(args.smi_at(index)); |
140 | 140 |
141 | 141 |
142 MUST_USE_RESULT static MaybeObject* DeepCopyBoilerplate(Isolate* isolate, | |
143 JSObject* boilerplate) { | |
144 StackLimitCheck check(isolate); | |
145 if (check.HasOverflowed()) return isolate->StackOverflow(); | |
146 | |
147 Heap* heap = isolate->heap(); | |
148 Object* result; | |
149 { MaybeObject* maybe_result = heap->CopyJSObject(boilerplate); | |
150 if (!maybe_result->ToObject(&result)) return maybe_result; | |
151 } | |
152 JSObject* copy = JSObject::cast(result); | |
153 | |
154 // Deep copy local properties. | |
155 if (copy->HasFastProperties()) { | |
156 FixedArray* properties = copy->properties(); | |
157 for (int i = 0; i < properties->length(); i++) { | |
158 Object* value = properties->get(i); | |
159 if (value->IsJSObject()) { | |
160 JSObject* js_object = JSObject::cast(value); | |
161 { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object); | |
162 if (!maybe_result->ToObject(&result)) return maybe_result; | |
163 } | |
164 properties->set(i, result); | |
165 } | |
166 } | |
167 int nof = copy->map()->inobject_properties(); | |
168 for (int i = 0; i < nof; i++) { | |
169 Object* value = copy->InObjectPropertyAt(i); | |
170 if (value->IsJSObject()) { | |
171 JSObject* js_object = JSObject::cast(value); | |
172 { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object); | |
173 if (!maybe_result->ToObject(&result)) return maybe_result; | |
174 } | |
175 copy->InObjectPropertyAtPut(i, result); | |
176 } | |
177 } | |
178 } else { | |
179 { MaybeObject* maybe_result = | |
180 heap->AllocateFixedArray(copy->NumberOfLocalProperties()); | |
181 if (!maybe_result->ToObject(&result)) return maybe_result; | |
182 } | |
183 FixedArray* names = FixedArray::cast(result); | |
184 copy->GetLocalPropertyNames(names, 0); | |
185 for (int i = 0; i < names->length(); i++) { | |
186 ASSERT(names->get(i)->IsString()); | |
187 String* key_string = String::cast(names->get(i)); | |
188 PropertyAttributes attributes = | |
189 copy->GetLocalPropertyAttribute(key_string); | |
190 // Only deep copy fields from the object literal expression. | |
191 // In particular, don't try to copy the length attribute of | |
192 // an array. | |
193 if (attributes != NONE) continue; | |
194 Object* value = | |
195 copy->GetProperty(key_string, &attributes)->ToObjectUnchecked(); | |
196 if (value->IsJSObject()) { | |
197 JSObject* js_object = JSObject::cast(value); | |
198 { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object); | |
199 if (!maybe_result->ToObject(&result)) return maybe_result; | |
200 } | |
201 { MaybeObject* maybe_result = | |
202 // Creating object copy for literals. No strict mode needed. | |
203 copy->SetProperty(key_string, result, NONE, kNonStrictMode); | |
204 if (!maybe_result->ToObject(&result)) return maybe_result; | |
205 } | |
206 } | |
207 } | |
208 } | |
209 | |
210 // Deep copy local elements. | |
211 // Pixel elements cannot be created using an object literal. | |
212 ASSERT(!copy->HasExternalArrayElements()); | |
213 switch (copy->GetElementsKind()) { | |
214 case FAST_SMI_ELEMENTS: | |
215 case FAST_ELEMENTS: | |
216 case FAST_HOLEY_SMI_ELEMENTS: | |
217 case FAST_HOLEY_ELEMENTS: { | |
218 FixedArray* elements = FixedArray::cast(copy->elements()); | |
219 if (elements->map() == heap->fixed_cow_array_map()) { | |
220 isolate->counters()->cow_arrays_created_runtime()->Increment(); | |
221 #ifdef DEBUG | |
222 for (int i = 0; i < elements->length(); i++) { | |
223 ASSERT(!elements->get(i)->IsJSObject()); | |
224 } | |
225 #endif | |
226 } else { | |
227 for (int i = 0; i < elements->length(); i++) { | |
228 Object* value = elements->get(i); | |
229 ASSERT(value->IsSmi() || | |
230 value->IsTheHole() || | |
231 (IsFastObjectElementsKind(copy->GetElementsKind()))); | |
232 if (value->IsJSObject()) { | |
233 JSObject* js_object = JSObject::cast(value); | |
234 { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, | |
235 js_object); | |
236 if (!maybe_result->ToObject(&result)) return maybe_result; | |
237 } | |
238 elements->set(i, result); | |
239 } | |
240 } | |
241 } | |
242 break; | |
243 } | |
244 case DICTIONARY_ELEMENTS: { | |
245 SeededNumberDictionary* element_dictionary = copy->element_dictionary(); | |
246 int capacity = element_dictionary->Capacity(); | |
247 for (int i = 0; i < capacity; i++) { | |
248 Object* k = element_dictionary->KeyAt(i); | |
249 if (element_dictionary->IsKey(k)) { | |
250 Object* value = element_dictionary->ValueAt(i); | |
251 if (value->IsJSObject()) { | |
252 JSObject* js_object = JSObject::cast(value); | |
253 { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, | |
254 js_object); | |
255 if (!maybe_result->ToObject(&result)) return maybe_result; | |
256 } | |
257 element_dictionary->ValueAtPut(i, result); | |
258 } | |
259 } | |
260 } | |
261 break; | |
262 } | |
263 case NON_STRICT_ARGUMENTS_ELEMENTS: | |
264 UNIMPLEMENTED(); | |
265 break; | |
266 case EXTERNAL_PIXEL_ELEMENTS: | |
267 case EXTERNAL_BYTE_ELEMENTS: | |
268 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | |
269 case EXTERNAL_SHORT_ELEMENTS: | |
270 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | |
271 case EXTERNAL_INT_ELEMENTS: | |
272 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | |
273 case EXTERNAL_FLOAT_ELEMENTS: | |
274 case EXTERNAL_DOUBLE_ELEMENTS: | |
275 case FAST_DOUBLE_ELEMENTS: | |
276 case FAST_HOLEY_DOUBLE_ELEMENTS: | |
277 // No contained objects, nothing to do. | |
278 break; | |
279 } | |
280 return copy; | |
281 } | |
282 | |
283 | |
284 static Handle<Map> ComputeObjectLiteralMap( | 142 static Handle<Map> ComputeObjectLiteralMap( |
285 Handle<Context> context, | 143 Handle<Context> context, |
286 Handle<FixedArray> constant_properties, | 144 Handle<FixedArray> constant_properties, |
287 bool* is_result_from_cache) { | 145 bool* is_result_from_cache) { |
288 Isolate* isolate = context->GetIsolate(); | 146 Isolate* isolate = context->GetIsolate(); |
289 int properties_length = constant_properties->length(); | 147 int properties_length = constant_properties->length(); |
290 int number_of_properties = properties_length / 2; | 148 int number_of_properties = properties_length / 2; |
291 // Check that there are only internal strings and array indices among keys. | 149 // Check that there are only internal strings and array indices among keys. |
292 int number_of_string_keys = 0; | 150 int number_of_string_keys = 0; |
293 for (int p = 0; p != properties_length; p += 2) { | 151 for (int p = 0; p != properties_length; p += 2) { |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
592 if (*boilerplate == isolate->heap()->undefined_value()) { | 450 if (*boilerplate == isolate->heap()->undefined_value()) { |
593 boilerplate = CreateObjectLiteralBoilerplate(isolate, | 451 boilerplate = CreateObjectLiteralBoilerplate(isolate, |
594 literals, | 452 literals, |
595 constant_properties, | 453 constant_properties, |
596 should_have_fast_elements, | 454 should_have_fast_elements, |
597 has_function_literal); | 455 has_function_literal); |
598 if (boilerplate.is_null()) return Failure::Exception(); | 456 if (boilerplate.is_null()) return Failure::Exception(); |
599 // Update the functions literal and return the boilerplate. | 457 // Update the functions literal and return the boilerplate. |
600 literals->set(literals_index, *boilerplate); | 458 literals->set(literals_index, *boilerplate); |
601 } | 459 } |
602 return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate)); | 460 return JSObject::cast(*boilerplate)->DeepCopy(isolate); |
603 } | 461 } |
604 | 462 |
605 | 463 |
606 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteralShallow) { | 464 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteralShallow) { |
607 HandleScope scope(isolate); | 465 HandleScope scope(isolate); |
608 ASSERT(args.length() == 4); | 466 ASSERT(args.length() == 4); |
609 CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0); | 467 CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0); |
610 CONVERT_SMI_ARG_CHECKED(literals_index, 1); | 468 CONVERT_SMI_ARG_CHECKED(literals_index, 1); |
611 CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2); | 469 CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2); |
612 CONVERT_SMI_ARG_CHECKED(flags, 3); | 470 CONVERT_SMI_ARG_CHECKED(flags, 3); |
(...skipping 26 matching lines...) Expand all Loading... |
639 // Check if boilerplate exists. If not, create it first. | 497 // Check if boilerplate exists. If not, create it first. |
640 Handle<Object> boilerplate(literals->get(literals_index), isolate); | 498 Handle<Object> boilerplate(literals->get(literals_index), isolate); |
641 if (*boilerplate == isolate->heap()->undefined_value()) { | 499 if (*boilerplate == isolate->heap()->undefined_value()) { |
642 ASSERT(*elements != isolate->heap()->empty_fixed_array()); | 500 ASSERT(*elements != isolate->heap()->empty_fixed_array()); |
643 boilerplate = | 501 boilerplate = |
644 Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements); | 502 Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements); |
645 if (boilerplate.is_null()) return Failure::Exception(); | 503 if (boilerplate.is_null()) return Failure::Exception(); |
646 // Update the functions literal and return the boilerplate. | 504 // Update the functions literal and return the boilerplate. |
647 literals->set(literals_index, *boilerplate); | 505 literals->set(literals_index, *boilerplate); |
648 } | 506 } |
649 return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate)); | 507 return JSObject::cast(*boilerplate)->DeepCopy(isolate); |
650 } | 508 } |
651 | 509 |
652 | 510 |
653 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralShallow) { | 511 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralShallow) { |
654 HandleScope scope(isolate); | 512 HandleScope scope(isolate); |
655 ASSERT(args.length() == 3); | 513 ASSERT(args.length() == 3); |
656 CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0); | 514 CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0); |
657 CONVERT_SMI_ARG_CHECKED(literals_index, 1); | 515 CONVERT_SMI_ARG_CHECKED(literals_index, 1); |
658 CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2); | 516 CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2); |
659 | 517 |
(...skipping 12491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13151 // Handle last resort GC and make sure to allow future allocations | 13009 // Handle last resort GC and make sure to allow future allocations |
13152 // to grow the heap without causing GCs (if possible). | 13010 // to grow the heap without causing GCs (if possible). |
13153 isolate->counters()->gc_last_resort_from_js()->Increment(); | 13011 isolate->counters()->gc_last_resort_from_js()->Increment(); |
13154 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 13012 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
13155 "Runtime::PerformGC"); | 13013 "Runtime::PerformGC"); |
13156 } | 13014 } |
13157 } | 13015 } |
13158 | 13016 |
13159 | 13017 |
13160 } } // namespace v8::internal | 13018 } } // namespace v8::internal |
OLD | NEW |