Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(209)

Side by Side Diff: src/runtime.cc

Issue 3144002: Copy-on-write arrays. (Closed)
Patch Set: Review fixes. Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/parser.cc ('k') | src/serialize.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 } 153 }
154 } 154 }
155 } 155 }
156 156
157 // Deep copy local elements. 157 // Deep copy local elements.
158 // Pixel elements cannot be created using an object literal. 158 // Pixel elements cannot be created using an object literal.
159 ASSERT(!copy->HasPixelElements() && !copy->HasExternalArrayElements()); 159 ASSERT(!copy->HasPixelElements() && !copy->HasExternalArrayElements());
160 switch (copy->GetElementsKind()) { 160 switch (copy->GetElementsKind()) {
161 case JSObject::FAST_ELEMENTS: { 161 case JSObject::FAST_ELEMENTS: {
162 FixedArray* elements = FixedArray::cast(copy->elements()); 162 FixedArray* elements = FixedArray::cast(copy->elements());
163 for (int i = 0; i < elements->length(); i++) { 163 if (elements->map() == Heap::fixed_cow_array_map()) {
164 Object* value = elements->get(i); 164 Counters::cow_arrays_created_runtime.Increment();
165 if (value->IsJSObject()) { 165 #ifdef DEBUG
166 JSObject* js_object = JSObject::cast(value); 166 for (int i = 0; i < elements->length(); i++) {
167 result = DeepCopyBoilerplate(js_object); 167 ASSERT(!elements->get(i)->IsJSObject());
168 if (result->IsFailure()) return result; 168 }
169 elements->set(i, result); 169 #endif
170 } else {
171 for (int i = 0; i < elements->length(); i++) {
172 Object* value = elements->get(i);
173 if (value->IsJSObject()) {
174 JSObject* js_object = JSObject::cast(value);
175 result = DeepCopyBoilerplate(js_object);
176 if (result->IsFailure()) return result;
177 elements->set(i, result);
178 }
170 } 179 }
171 } 180 }
172 break; 181 break;
173 } 182 }
174 case JSObject::DICTIONARY_ELEMENTS: { 183 case JSObject::DICTIONARY_ELEMENTS: {
175 NumberDictionary* element_dictionary = copy->element_dictionary(); 184 NumberDictionary* element_dictionary = copy->element_dictionary();
176 int capacity = element_dictionary->Capacity(); 185 int capacity = element_dictionary->Capacity();
177 for (int i = 0; i < capacity; i++) { 186 for (int i = 0; i < capacity; i++) {
178 Object* k = element_dictionary->KeyAt(i); 187 Object* k = element_dictionary->KeyAt(i);
179 if (element_dictionary->IsKey(k)) { 188 if (element_dictionary->IsKey(k)) {
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 345
337 346
338 static Handle<Object> CreateArrayLiteralBoilerplate( 347 static Handle<Object> CreateArrayLiteralBoilerplate(
339 Handle<FixedArray> literals, 348 Handle<FixedArray> literals,
340 Handle<FixedArray> elements) { 349 Handle<FixedArray> elements) {
341 // Create the JSArray. 350 // Create the JSArray.
342 Handle<JSFunction> constructor( 351 Handle<JSFunction> constructor(
343 JSFunction::GlobalContextFromLiterals(*literals)->array_function()); 352 JSFunction::GlobalContextFromLiterals(*literals)->array_function());
344 Handle<Object> object = Factory::NewJSObject(constructor); 353 Handle<Object> object = Factory::NewJSObject(constructor);
345 354
346 Handle<Object> copied_elements = Factory::CopyFixedArray(elements); 355 const bool is_cow = (elements->map() == Heap::fixed_cow_array_map());
356 Handle<FixedArray> copied_elements =
357 is_cow ? elements : Factory::CopyFixedArray(elements);
347 358
348 Handle<FixedArray> content = Handle<FixedArray>::cast(copied_elements); 359 Handle<FixedArray> content = Handle<FixedArray>::cast(copied_elements);
349 for (int i = 0; i < content->length(); i++) { 360 if (is_cow) {
350 if (content->get(i)->IsFixedArray()) { 361 #ifdef DEBUG
351 // The value contains the constant_properties of a 362 // Copy-on-write arrays must be shallow (and simple).
352 // simple object literal. 363 for (int i = 0; i < content->length(); i++) {
353 Handle<FixedArray> fa(FixedArray::cast(content->get(i))); 364 ASSERT(!content->get(i)->IsFixedArray());
354 Handle<Object> result = 365 }
355 CreateLiteralBoilerplate(literals, fa); 366 #endif
356 if (result.is_null()) return result; 367 } else {
357 content->set(i, *result); 368 for (int i = 0; i < content->length(); i++) {
369 if (content->get(i)->IsFixedArray()) {
370 // The value contains the constant_properties of a
371 // simple object literal.
372 Handle<FixedArray> fa(FixedArray::cast(content->get(i)));
373 Handle<Object> result =
374 CreateLiteralBoilerplate(literals, fa);
375 if (result.is_null()) return result;
376 content->set(i, *result);
377 }
358 } 378 }
359 } 379 }
360 380
361 // Set the elements. 381 // Set the elements.
362 Handle<JSArray>::cast(object)->SetContent(*content); 382 Handle<JSArray>::cast(object)->SetContent(*content);
363 return object; 383 return object;
364 } 384 }
365 385
366 386
367 static Handle<Object> CreateLiteralBoilerplate( 387 static Handle<Object> CreateLiteralBoilerplate(
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 CONVERT_ARG_CHECKED(FixedArray, elements, 2); 496 CONVERT_ARG_CHECKED(FixedArray, elements, 2);
477 497
478 // Check if boilerplate exists. If not, create it first. 498 // Check if boilerplate exists. If not, create it first.
479 Handle<Object> boilerplate(literals->get(literals_index)); 499 Handle<Object> boilerplate(literals->get(literals_index));
480 if (*boilerplate == Heap::undefined_value()) { 500 if (*boilerplate == Heap::undefined_value()) {
481 boilerplate = CreateArrayLiteralBoilerplate(literals, elements); 501 boilerplate = CreateArrayLiteralBoilerplate(literals, elements);
482 if (boilerplate.is_null()) return Failure::Exception(); 502 if (boilerplate.is_null()) return Failure::Exception();
483 // Update the functions literal and return the boilerplate. 503 // Update the functions literal and return the boilerplate.
484 literals->set(literals_index, *boilerplate); 504 literals->set(literals_index, *boilerplate);
485 } 505 }
506 if (JSObject::cast(*boilerplate)->elements()->map() ==
507 Heap::fixed_cow_array_map()) {
508 Counters::cow_arrays_created_runtime.Increment();
509 }
486 return Heap::CopyJSObject(JSObject::cast(*boilerplate)); 510 return Heap::CopyJSObject(JSObject::cast(*boilerplate));
487 } 511 }
488 512
489 513
490 static Object* Runtime_CreateCatchExtensionObject(Arguments args) { 514 static Object* Runtime_CreateCatchExtensionObject(Arguments args) {
491 ASSERT(args.length() == 2); 515 ASSERT(args.length() == 2);
492 CONVERT_CHECKED(String, key, args[0]); 516 CONVERT_CHECKED(String, key, args[0]);
493 Object* value = args[1]; 517 Object* value = args[1];
494 // Create a catch context extension object. 518 // Create a catch context extension object.
495 JSFunction* constructor = 519 JSFunction* constructor =
(...skipping 6196 matching lines...) Expand 10 before | Expand all | Expand 10 after
6692 static Object* Runtime_DateYMDFromTime(Arguments args) { 6716 static Object* Runtime_DateYMDFromTime(Arguments args) {
6693 NoHandleAllocation ha; 6717 NoHandleAllocation ha;
6694 ASSERT(args.length() == 2); 6718 ASSERT(args.length() == 2);
6695 6719
6696 CONVERT_DOUBLE_CHECKED(t, args[0]); 6720 CONVERT_DOUBLE_CHECKED(t, args[0]);
6697 CONVERT_CHECKED(JSArray, res_array, args[1]); 6721 CONVERT_CHECKED(JSArray, res_array, args[1]);
6698 6722
6699 int year, month, day; 6723 int year, month, day;
6700 DateYMDFromTime(static_cast<int>(floor(t / 86400000)), year, month, day); 6724 DateYMDFromTime(static_cast<int>(floor(t / 86400000)), year, month, day);
6701 6725
6702 res_array->SetElement(0, Smi::FromInt(year)); 6726 RUNTIME_ASSERT(res_array->elements()->map() == Heap::fixed_array_map());
6703 res_array->SetElement(1, Smi::FromInt(month)); 6727 FixedArray* elms = FixedArray::cast(res_array->elements());
6704 res_array->SetElement(2, Smi::FromInt(day)); 6728 RUNTIME_ASSERT(elms->length() == 3);
6729
6730 elms->set(0, Smi::FromInt(year));
6731 elms->set(1, Smi::FromInt(month));
6732 elms->set(2, Smi::FromInt(day));
6705 6733
6706 return Heap::undefined_value(); 6734 return Heap::undefined_value();
6707 } 6735 }
6708 6736
6709 6737
6710 static Object* Runtime_NewArgumentsFast(Arguments args) { 6738 static Object* Runtime_NewArgumentsFast(Arguments args) {
6711 NoHandleAllocation ha; 6739 NoHandleAllocation ha;
6712 ASSERT(args.length() == 3); 6740 ASSERT(args.length() == 3);
6713 6741
6714 JSFunction* callee = JSFunction::cast(args[0]); 6742 JSFunction* callee = JSFunction::cast(args[0]);
(...skipping 1335 matching lines...) Expand 10 before | Expand all | Expand 10 after
8050 } 8078 }
8051 8079
8052 8080
8053 // Move contents of argument 0 (an array) to argument 1 (an array) 8081 // Move contents of argument 0 (an array) to argument 1 (an array)
8054 static Object* Runtime_MoveArrayContents(Arguments args) { 8082 static Object* Runtime_MoveArrayContents(Arguments args) {
8055 ASSERT(args.length() == 2); 8083 ASSERT(args.length() == 2);
8056 CONVERT_CHECKED(JSArray, from, args[0]); 8084 CONVERT_CHECKED(JSArray, from, args[0]);
8057 CONVERT_CHECKED(JSArray, to, args[1]); 8085 CONVERT_CHECKED(JSArray, to, args[1]);
8058 HeapObject* new_elements = from->elements(); 8086 HeapObject* new_elements = from->elements();
8059 Object* new_map; 8087 Object* new_map;
8060 if (new_elements->map() == Heap::fixed_array_map()) { 8088 if (new_elements->map() == Heap::fixed_array_map() ||
8089 new_elements->map() == Heap::fixed_cow_array_map()) {
8061 new_map = to->map()->GetFastElementsMap(); 8090 new_map = to->map()->GetFastElementsMap();
8062 } else { 8091 } else {
8063 new_map = to->map()->GetSlowElementsMap(); 8092 new_map = to->map()->GetSlowElementsMap();
8064 } 8093 }
8065 if (new_map->IsFailure()) return new_map; 8094 if (new_map->IsFailure()) return new_map;
8066 to->set_map(Map::cast(new_map)); 8095 to->set_map(Map::cast(new_map));
8067 to->set_elements(new_elements); 8096 to->set_elements(new_elements);
8068 to->set_length(from->length()); 8097 to->set_length(from->length());
8069 Object* obj = from->ResetElements(); 8098 Object* obj = from->ResetElements();
8070 if (obj->IsFailure()) return obj; 8099 if (obj->IsFailure()) return obj;
(...skipping 2550 matching lines...) Expand 10 before | Expand all | Expand 10 after
10621 } else { 10650 } else {
10622 // Handle last resort GC and make sure to allow future allocations 10651 // Handle last resort GC and make sure to allow future allocations
10623 // to grow the heap without causing GCs (if possible). 10652 // to grow the heap without causing GCs (if possible).
10624 Counters::gc_last_resort_from_js.Increment(); 10653 Counters::gc_last_resort_from_js.Increment();
10625 Heap::CollectAllGarbage(false); 10654 Heap::CollectAllGarbage(false);
10626 } 10655 }
10627 } 10656 }
10628 10657
10629 10658
10630 } } // namespace v8::internal 10659 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/parser.cc ('k') | src/serialize.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698