| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |