| 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 |