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

Side by Side Diff: src/builtins.cc

Issue 650043: Faster moving FixedArray elements around. (Closed)
Patch Set: First round of Soren's comments Created 10 years, 10 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/array.js ('k') | src/objects.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-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 344 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 } 355 }
356 elms->set(len - 1, Heap::the_hole_value()); 356 elms->set(len - 1, Heap::the_hole_value());
357 357
358 // Set the length. 358 // Set the length.
359 array->set_length(Smi::FromInt(len - 1)); 359 array->set_length(Smi::FromInt(len - 1));
360 360
361 return first; 361 return first;
362 } 362 }
363 363
364 364
365 static Object* CallJsBuiltin(const char* name,
366 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
367 HandleScope handleScope;
368
369 Handle<Object> js_builtin =
370 GetProperty(Handle<JSObject>(Top::global_context()->builtins()),
371 name);
372 ASSERT(js_builtin->IsJSFunction());
373 Handle<JSFunction> function(Handle<JSFunction>::cast(js_builtin));
374 Vector<Object**> argv(Vector<Object**>::New(args.length() - 1));
375 int n_args = args.length() - 1;
376 for (int i = 0; i < n_args; i++) {
377 argv[i] = &args[i + 1];
378 }
379 bool pending_exception = false;
380 Handle<Object> result = Execution::Call(function,
381 args.receiver(),
382 n_args,
383 argv.start(),
384 &pending_exception);
385 if (pending_exception) return Failure::Exception();
386 return *result;
387 }
388
389
390 static bool ArrayPrototypeHasNoElements() {
391 // This method depends on non writability of Object and Array prototype
392 // fields.
393 Context* global_context = Top::context()->global_context();
394 // Array.prototype
395 JSObject* proto =
396 JSObject::cast(global_context->array_function()->prototype());
397 if (proto->elements() != Heap::empty_fixed_array()) return false;
398 // Hidden prototype
399 proto = JSObject::cast(proto->GetPrototype());
400 ASSERT(proto->elements() == Heap::empty_fixed_array());
401 // Object.prototype
402 proto = JSObject::cast(proto->GetPrototype());
403 if (proto != global_context->initial_object_prototype()) return false;
404 if (proto->elements() != Heap::empty_fixed_array()) return false;
405 ASSERT(proto->GetPrototype()->IsNull());
406 return true;
407 }
408
409
365 BUILTIN(ArrayUnshift) { 410 BUILTIN(ArrayUnshift) {
411 if (!ArrayPrototypeHasNoElements()) {
412 return CallJsBuiltin("ArrayUnshift", args);
413 }
414
366 JSArray* array = JSArray::cast(*args.receiver()); 415 JSArray* array = JSArray::cast(*args.receiver());
367 ASSERT(array->HasFastElements()); 416 ASSERT(array->HasFastElements());
368 417
369 int len = Smi::cast(array->length())->value(); 418 int len = Smi::cast(array->length())->value();
370 int to_add = args.length() - 1; 419 int to_add = args.length() - 1;
371 // Note that we cannot quit early if to_add == 0 as 420 // Note that we cannot quit early if to_add == 0 as
372 // values should be lifted from prototype into 421 // values should be lifted from prototype into
373 // the array. 422 // the array.
374 423
375 int new_length = len + to_add; 424 int new_length = len + to_add;
376 // Currently fixed arrays cannot grow too big, so 425 // Currently fixed arrays cannot grow too big, so
377 // we should never hit this case. 426 // we should never hit this case.
378 ASSERT(to_add <= (Smi::kMaxValue - len)); 427 ASSERT(to_add <= (Smi::kMaxValue - len));
379 428
380 FixedArray* elms = FixedArray::cast(array->elements()); 429 FixedArray* elms = FixedArray::cast(array->elements());
381 430
382 // Fetch the prototype.
383 JSFunction* array_function =
384 Top::context()->global_context()->array_function();
385 JSObject* prototype = JSObject::cast(array_function->prototype());
386
387 if (new_length > elms->length()) { 431 if (new_length > elms->length()) {
388 // New backing storage is needed. 432 // New backing storage is needed.
389 int capacity = new_length + (new_length >> 1) + 16; 433 int capacity = new_length + (new_length >> 1) + 16;
390 Object* obj = Heap::AllocateFixedArrayWithHoles(capacity); 434 Object* obj = Heap::AllocateRawFixedArray(capacity);
391 if (obj->IsFailure()) return obj; 435 if (obj->IsFailure()) return obj;
392 436
393 AssertNoAllocation no_gc; 437 reinterpret_cast<Array*>(obj)->set_map(Heap::fixed_array_map());
394 FixedArray* new_elms = FixedArray::cast(obj); 438 FixedArray* new_elms = FixedArray::cast(obj);
395 WriteBarrierMode mode = new_elms->GetWriteBarrierMode(no_gc); 439 new_elms->set_length(capacity);
396 // Fill out the new array with old elements. 440
397 for (int i = 0; i < len; i++) 441 Object** new_elms_data = new_elms->data_start();
398 new_elms->set(to_add + i, 442 memcpy(new_elms_data + to_add, elms->data_start(), len * kPointerSize);
399 GetElementToMove(i, elms, prototype), 443
400 mode); 444 // Let's hope that compiler can easily optimize this filling code.
445 Object* hole = Heap::the_hole_value();
446 for (int i = new_length; i < capacity; i++) {
447 new_elms_data[i] = hole;
448 }
401 449
402 elms = new_elms; 450 elms = new_elms;
403 array->set_elements(elms); 451 array->set_elements(elms);
404 } else { 452 } else {
405 AssertNoAllocation no_gc; 453 memmove(elms->data_start() + to_add,
406 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); 454 elms->data_start(),
407 455 len * kPointerSize);
408 // Move elements to the right
409 for (int i = 0; i < len; i++) {
410 elms->set(new_length - i - 1,
411 GetElementToMove(len - i - 1, elms, prototype),
412 mode);
413 }
414 } 456 }
415 457
416 // Add the provided values. 458 // Add the provided values.
417 AssertNoAllocation no_gc; 459 AssertNoAllocation no_gc;
460 for (int i = 0; i < to_add; i++) {
461 elms->set(i, args[i + 1], SKIP_WRITE_BARRIER);
462 }
418 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); 463 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
419 for (int i = 0; i < to_add; i++) { 464 if (mode == UPDATE_WRITE_BARRIER) {
420 elms->set(i, args[i + 1], mode); 465 Address address = elms->address();
466 for (int i = 0; i < new_length; i++) {
467 Heap::RecordWrite(address, FixedArray::kHeaderSize + i * kPointerSize);
468 }
421 } 469 }
422 470
423 // Set the length. 471 // Set the length.
424 array->set_length(Smi::FromInt(new_length)); 472 array->set_length(Smi::FromInt(new_length));
425 return Smi::FromInt(new_length); 473 return Smi::FromInt(new_length);
426 } 474 }
427 475
428 476
429 static Object* CallJsBuiltin(const char* name,
430 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
431 HandleScope handleScope;
432
433 Handle<Object> js_builtin =
434 GetProperty(Handle<JSObject>(Top::global_context()->builtins()),
435 name);
436 ASSERT(js_builtin->IsJSFunction());
437 Handle<JSFunction> function(Handle<JSFunction>::cast(js_builtin));
438 Vector<Object**> argv(Vector<Object**>::New(args.length() - 1));
439 int n_args = args.length() - 1;
440 for (int i = 0; i < n_args; i++) {
441 argv[i] = &args[i + 1];
442 }
443 bool pending_exception = false;
444 Handle<Object> result = Execution::Call(function,
445 args.receiver(),
446 n_args,
447 argv.start(),
448 &pending_exception);
449 if (pending_exception) return Failure::Exception();
450 return *result;
451 }
452
453
454 BUILTIN(ArraySlice) { 477 BUILTIN(ArraySlice) {
455 JSArray* array = JSArray::cast(*args.receiver()); 478 JSArray* array = JSArray::cast(*args.receiver());
456 ASSERT(array->HasFastElements()); 479 ASSERT(array->HasFastElements());
457 480
458 int len = Smi::cast(array->length())->value(); 481 int len = Smi::cast(array->length())->value();
459 482
460 int n_arguments = args.length() - 1; 483 int n_arguments = args.length() - 1;
461 484
462 // Note carefully choosen defaults---if argument is missing, 485 // Note carefully choosen defaults---if argument is missing,
463 // it's undefined which gets converted to 0 for relativeStart 486 // it's undefined which gets converted to 0 for relativeStart
(...skipping 847 matching lines...) Expand 10 before | Expand all | Expand 10 after
1311 if (entry->contains(pc)) { 1334 if (entry->contains(pc)) {
1312 return names_[i]; 1335 return names_[i];
1313 } 1336 }
1314 } 1337 }
1315 } 1338 }
1316 return NULL; 1339 return NULL;
1317 } 1340 }
1318 1341
1319 1342
1320 } } // namespace v8::internal 1343 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/array.js ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698