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

Side by Side Diff: src/builtins.cc

Issue 8139027: Version 3.6.5 (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: '' Created 9 years, 2 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 | Annotate | Revision Log
« no previous file with comments | « src/bootstrapper.cc ('k') | src/code-stubs.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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 15 matching lines...) Expand all
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "api.h" 30 #include "api.h"
31 #include "arguments.h" 31 #include "arguments.h"
32 #include "bootstrapper.h" 32 #include "bootstrapper.h"
33 #include "builtins.h" 33 #include "builtins.h"
34 #include "gdb-jit.h" 34 #include "gdb-jit.h"
35 #include "ic-inl.h" 35 #include "ic-inl.h"
36 #include "mark-compact.h"
36 #include "vm-state-inl.h" 37 #include "vm-state-inl.h"
37 38
38 namespace v8 { 39 namespace v8 {
39 namespace internal { 40 namespace internal {
40 41
41 namespace { 42 namespace {
42 43
43 // Arguments object passed to C++ builtins. 44 // Arguments object passed to C++ builtins.
44 template <BuiltinExtraArguments extra_args> 45 template <BuiltinExtraArguments extra_args>
45 class BuiltinArguments : public Arguments { 46 class BuiltinArguments : public Arguments {
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 JSFunction* constructor = 196 JSFunction* constructor =
196 isolate->context()->global_context()->array_function(); 197 isolate->context()->global_context()->array_function();
197 Object* obj; 198 Object* obj;
198 { MaybeObject* maybe_obj = heap->AllocateJSObject(constructor); 199 { MaybeObject* maybe_obj = heap->AllocateJSObject(constructor);
199 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 200 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
200 } 201 }
201 array = JSArray::cast(obj); 202 array = JSArray::cast(obj);
202 } 203 }
203 204
204 // 'array' now contains the JSArray we should initialize. 205 // 'array' now contains the JSArray we should initialize.
205 ASSERT(array->HasFastElements()); 206 ASSERT(array->HasFastTypeElements());
206 207
207 // Optimize the case where there is one argument and the argument is a 208 // Optimize the case where there is one argument and the argument is a
208 // small smi. 209 // small smi.
209 if (args.length() == 2) { 210 if (args.length() == 2) {
210 Object* obj = args[1]; 211 Object* obj = args[1];
211 if (obj->IsSmi()) { 212 if (obj->IsSmi()) {
212 int len = Smi::cast(obj)->value(); 213 int len = Smi::cast(obj)->value();
213 if (len >= 0 && len < JSObject::kInitialMaxFastElementArray) { 214 if (len >= 0 && len < JSObject::kInitialMaxFastElementArray) {
214 Object* obj; 215 Object* obj;
215 { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(len); 216 { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(len);
216 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 217 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
217 } 218 }
218 array->SetContent(FixedArray::cast(obj)); 219 MaybeObject* maybe_obj = array->SetContent(FixedArray::cast(obj));
220 if (maybe_obj->IsFailure()) return maybe_obj;
219 return array; 221 return array;
220 } 222 }
221 } 223 }
222 // Take the argument as the length. 224 // Take the argument as the length.
223 { MaybeObject* maybe_obj = array->Initialize(0); 225 { MaybeObject* maybe_obj = array->Initialize(0);
224 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 226 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
225 } 227 }
226 return array->SetElementsLength(args[1]); 228 return array->SetElementsLength(args[1]);
227 } 229 }
228 230
229 // Optimize the case where there are no parameters passed. 231 // Optimize the case where there are no parameters passed.
230 if (args.length() == 1) { 232 if (args.length() == 1) {
231 return array->Initialize(JSArray::kPreallocatedArrayElements); 233 return array->Initialize(JSArray::kPreallocatedArrayElements);
232 } 234 }
233 235
234 // Take the arguments as elements. 236 // Take the arguments as elements.
235 int number_of_elements = args.length() - 1; 237 int number_of_elements = args.length() - 1;
236 Smi* len = Smi::FromInt(number_of_elements); 238 Smi* len = Smi::FromInt(number_of_elements);
237 Object* obj; 239 Object* obj;
238 { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(len->value()); 240 { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(len->value());
239 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 241 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
240 } 242 }
241 243
244 // Set length and elements on the array.
245 if (FLAG_smi_only_arrays) {
246 MaybeObject* maybe_object =
247 array->EnsureCanContainElements(FixedArray::cast(obj));
248 if (maybe_object->IsFailure()) return maybe_object;
249 }
250
242 AssertNoAllocation no_gc; 251 AssertNoAllocation no_gc;
243 FixedArray* elms = FixedArray::cast(obj); 252 FixedArray* elms = FixedArray::cast(obj);
244 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); 253 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
245 // Fill in the content 254 // Fill in the content
246 for (int index = 0; index < number_of_elements; index++) { 255 for (int index = 0; index < number_of_elements; index++) {
247 elms->set(index, args[index+1], mode); 256 elms->set(index, args[index+1], mode);
248 } 257 }
249 258
250 // Set length and elements on the array.
251 array->set_elements(FixedArray::cast(obj)); 259 array->set_elements(FixedArray::cast(obj));
252 array->set_length(len); 260 array->set_length(len);
253 261
254 return array; 262 return array;
255 } 263 }
256 264
257 265
258 MUST_USE_RESULT static MaybeObject* AllocateJSArray(Heap* heap) { 266 MUST_USE_RESULT static MaybeObject* AllocateJSArray(Heap* heap) {
259 JSFunction* array_function = 267 JSFunction* array_function =
260 heap->isolate()->context()->global_context()->array_function(); 268 heap->isolate()->context()->global_context()->array_function();
(...skipping 27 matching lines...) Expand all
288 ASSERT(dst != src); // Use MoveElements instead. 296 ASSERT(dst != src); // Use MoveElements instead.
289 ASSERT(dst->map() != HEAP->fixed_cow_array_map()); 297 ASSERT(dst->map() != HEAP->fixed_cow_array_map());
290 ASSERT(len > 0); 298 ASSERT(len > 0);
291 CopyWords(dst->data_start() + dst_index, 299 CopyWords(dst->data_start() + dst_index,
292 src->data_start() + src_index, 300 src->data_start() + src_index,
293 len); 301 len);
294 WriteBarrierMode mode = dst->GetWriteBarrierMode(*no_gc); 302 WriteBarrierMode mode = dst->GetWriteBarrierMode(*no_gc);
295 if (mode == UPDATE_WRITE_BARRIER) { 303 if (mode == UPDATE_WRITE_BARRIER) {
296 heap->RecordWrites(dst->address(), dst->OffsetOfElementAt(dst_index), len); 304 heap->RecordWrites(dst->address(), dst->OffsetOfElementAt(dst_index), len);
297 } 305 }
306 heap->incremental_marking()->RecordWrites(dst);
298 } 307 }
299 308
300 309
301 static void MoveElements(Heap* heap, 310 static void MoveElements(Heap* heap,
302 AssertNoAllocation* no_gc, 311 AssertNoAllocation* no_gc,
303 FixedArray* dst, 312 FixedArray* dst,
304 int dst_index, 313 int dst_index,
305 FixedArray* src, 314 FixedArray* src,
306 int src_index, 315 int src_index,
307 int len) { 316 int len) {
308 ASSERT(dst->map() != HEAP->fixed_cow_array_map()); 317 ASSERT(dst->map() != HEAP->fixed_cow_array_map());
309 memmove(dst->data_start() + dst_index, 318 memmove(dst->data_start() + dst_index,
310 src->data_start() + src_index, 319 src->data_start() + src_index,
311 len * kPointerSize); 320 len * kPointerSize);
312 WriteBarrierMode mode = dst->GetWriteBarrierMode(*no_gc); 321 WriteBarrierMode mode = dst->GetWriteBarrierMode(*no_gc);
313 if (mode == UPDATE_WRITE_BARRIER) { 322 if (mode == UPDATE_WRITE_BARRIER) {
314 heap->RecordWrites(dst->address(), dst->OffsetOfElementAt(dst_index), len); 323 heap->RecordWrites(dst->address(), dst->OffsetOfElementAt(dst_index), len);
315 } 324 }
325 heap->incremental_marking()->RecordWrites(dst);
316 } 326 }
317 327
318 328
319 static void FillWithHoles(Heap* heap, FixedArray* dst, int from, int to) { 329 static void FillWithHoles(Heap* heap, FixedArray* dst, int from, int to) {
320 ASSERT(dst->map() != heap->fixed_cow_array_map()); 330 ASSERT(dst->map() != heap->fixed_cow_array_map());
321 MemsetPointer(dst->data_start() + from, heap->the_hole_value(), to - from); 331 MemsetPointer(dst->data_start() + from, heap->the_hole_value(), to - from);
322 } 332 }
323 333
324 334
325 static FixedArray* LeftTrimFixedArray(Heap* heap, 335 static FixedArray* LeftTrimFixedArray(Heap* heap,
(...skipping 25 matching lines...) Expand all
351 } 361 }
352 } 362 }
353 // Technically in new space this write might be omitted (except for 363 // Technically in new space this write might be omitted (except for
354 // debug mode which iterates through the heap), but to play safer 364 // debug mode which iterates through the heap), but to play safer
355 // we still do it. 365 // we still do it.
356 heap->CreateFillerObjectAt(elms->address(), to_trim * kPointerSize); 366 heap->CreateFillerObjectAt(elms->address(), to_trim * kPointerSize);
357 367
358 former_start[to_trim] = heap->fixed_array_map(); 368 former_start[to_trim] = heap->fixed_array_map();
359 former_start[to_trim + 1] = Smi::FromInt(len - to_trim); 369 former_start[to_trim + 1] = Smi::FromInt(len - to_trim);
360 370
371 // Maintain marking consistency for HeapObjectIterator and
372 // IncrementalMarking.
373 int size_delta = to_trim * kPointerSize;
374 if (heap->marking()->TransferMark(elms->address(),
375 elms->address() + size_delta)) {
376 MemoryChunk::IncrementLiveBytes(elms->address(), -size_delta);
377 }
378
361 return FixedArray::cast(HeapObject::FromAddress( 379 return FixedArray::cast(HeapObject::FromAddress(
362 elms->address() + to_trim * kPointerSize)); 380 elms->address() + to_trim * kPointerSize));
363 } 381 }
364 382
365 383
366 static bool ArrayPrototypeHasNoElements(Heap* heap, 384 static bool ArrayPrototypeHasNoElements(Heap* heap,
367 Context* global_context, 385 Context* global_context,
368 JSObject* array_proto) { 386 JSObject* array_proto) {
369 // This method depends on non writability of Object and Array prototype 387 // This method depends on non writability of Object and Array prototype
370 // fields. 388 // fields.
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 GetProperty(Handle<JSObject>( 434 GetProperty(Handle<JSObject>(
417 isolate->global_context()->builtins()), 435 isolate->global_context()->builtins()),
418 name); 436 name);
419 ASSERT(js_builtin->IsJSFunction()); 437 ASSERT(js_builtin->IsJSFunction());
420 Handle<JSFunction> function(Handle<JSFunction>::cast(js_builtin)); 438 Handle<JSFunction> function(Handle<JSFunction>::cast(js_builtin));
421 ScopedVector<Object**> argv(args.length() - 1); 439 ScopedVector<Object**> argv(args.length() - 1);
422 int n_args = args.length() - 1; 440 int n_args = args.length() - 1;
423 for (int i = 0; i < n_args; i++) { 441 for (int i = 0; i < n_args; i++) {
424 argv[i] = args.at<Object>(i + 1).location(); 442 argv[i] = args.at<Object>(i + 1).location();
425 } 443 }
426 bool pending_exception = false; 444 bool pending_exception;
427 Handle<Object> result = Execution::Call(function, 445 Handle<Object> result = Execution::Call(function,
428 args.receiver(), 446 args.receiver(),
429 n_args, 447 n_args,
430 argv.start(), 448 argv.start(),
431 &pending_exception); 449 &pending_exception);
432 if (pending_exception) return Failure::Exception(); 450 if (pending_exception) return Failure::Exception();
433 return *result; 451 return *result;
434 } 452 }
435 453
436 454
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 } 486 }
469 FixedArray* new_elms = FixedArray::cast(obj); 487 FixedArray* new_elms = FixedArray::cast(obj);
470 488
471 AssertNoAllocation no_gc; 489 AssertNoAllocation no_gc;
472 if (len > 0) { 490 if (len > 0) {
473 CopyElements(heap, &no_gc, new_elms, 0, elms, 0, len); 491 CopyElements(heap, &no_gc, new_elms, 0, elms, 0, len);
474 } 492 }
475 FillWithHoles(heap, new_elms, new_length, capacity); 493 FillWithHoles(heap, new_elms, new_length, capacity);
476 494
477 elms = new_elms; 495 elms = new_elms;
478 array->set_elements(elms);
479 } 496 }
480 497
498 MaybeObject* maybe = array->EnsureCanContainElements(&args, 1, to_add);
499 if (maybe->IsFailure()) return maybe;
500
481 // Add the provided values. 501 // Add the provided values.
482 AssertNoAllocation no_gc; 502 AssertNoAllocation no_gc;
483 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); 503 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
484 for (int index = 0; index < to_add; index++) { 504 for (int index = 0; index < to_add; index++) {
485 elms->set(index + len, args[index + 1], mode); 505 elms->set(index + len, args[index + 1], mode);
486 } 506 }
487 507
508 if (elms != array->elements()) {
509 array->set_elements(elms);
510 }
511
488 // Set the length. 512 // Set the length.
489 array->set_length(Smi::FromInt(new_length)); 513 array->set_length(Smi::FromInt(new_length));
490 return Smi::FromInt(new_length); 514 return Smi::FromInt(new_length);
491 } 515 }
492 516
493 517
494 BUILTIN(ArrayPop) { 518 BUILTIN(ArrayPop) {
495 Heap* heap = isolate->heap(); 519 Heap* heap = isolate->heap();
496 Object* receiver = *args.receiver(); 520 Object* receiver = *args.receiver();
497 Object* elms_obj; 521 Object* elms_obj;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
532 EnsureJSArrayWithWritableFastElements(heap, receiver); 556 EnsureJSArrayWithWritableFastElements(heap, receiver);
533 if (maybe_elms_obj == NULL) 557 if (maybe_elms_obj == NULL)
534 return CallJsBuiltin(isolate, "ArrayShift", args); 558 return CallJsBuiltin(isolate, "ArrayShift", args);
535 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; 559 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
536 } 560 }
537 if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) { 561 if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) {
538 return CallJsBuiltin(isolate, "ArrayShift", args); 562 return CallJsBuiltin(isolate, "ArrayShift", args);
539 } 563 }
540 FixedArray* elms = FixedArray::cast(elms_obj); 564 FixedArray* elms = FixedArray::cast(elms_obj);
541 JSArray* array = JSArray::cast(receiver); 565 JSArray* array = JSArray::cast(receiver);
542 ASSERT(array->HasFastElements()); 566 ASSERT(array->HasFastTypeElements());
543 567
544 int len = Smi::cast(array->length())->value(); 568 int len = Smi::cast(array->length())->value();
545 if (len == 0) return heap->undefined_value(); 569 if (len == 0) return heap->undefined_value();
546 570
547 // Get first element 571 // Get first element
548 Object* first = elms->get(0); 572 Object* first = elms->get(0);
549 if (first->IsTheHole()) { 573 if (first->IsTheHole()) {
550 first = heap->undefined_value(); 574 first = heap->undefined_value();
551 } 575 }
552 576
553 if (!heap->lo_space()->Contains(elms)) { 577 if (!heap->lo_space()->Contains(elms)) {
554 // As elms still in the same space they used to be, 578 array->set_elements(LeftTrimFixedArray(heap, elms, 1));
555 // there is no need to update region dirty mark.
556 array->set_elements(LeftTrimFixedArray(heap, elms, 1), SKIP_WRITE_BARRIER);
557 } else { 579 } else {
558 // Shift the elements. 580 // Shift the elements.
559 AssertNoAllocation no_gc; 581 AssertNoAllocation no_gc;
560 MoveElements(heap, &no_gc, elms, 0, elms, 1, len - 1); 582 MoveElements(heap, &no_gc, elms, 0, elms, 1, len - 1);
561 elms->set(len - 1, heap->the_hole_value()); 583 elms->set(len - 1, heap->the_hole_value());
562 } 584 }
563 585
564 // Set the length. 586 // Set the length.
565 array->set_length(Smi::FromInt(len - 1)); 587 array->set_length(Smi::FromInt(len - 1));
566 588
567 return first; 589 return first;
568 } 590 }
569 591
570 592
571 BUILTIN(ArrayUnshift) { 593 BUILTIN(ArrayUnshift) {
572 Heap* heap = isolate->heap(); 594 Heap* heap = isolate->heap();
573 Object* receiver = *args.receiver(); 595 Object* receiver = *args.receiver();
574 Object* elms_obj; 596 Object* elms_obj;
575 { MaybeObject* maybe_elms_obj = 597 { MaybeObject* maybe_elms_obj =
576 EnsureJSArrayWithWritableFastElements(heap, receiver); 598 EnsureJSArrayWithWritableFastElements(heap, receiver);
577 if (maybe_elms_obj == NULL) 599 if (maybe_elms_obj == NULL)
578 return CallJsBuiltin(isolate, "ArrayUnshift", args); 600 return CallJsBuiltin(isolate, "ArrayUnshift", args);
579 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; 601 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
580 } 602 }
581 if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) { 603 if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) {
582 return CallJsBuiltin(isolate, "ArrayUnshift", args); 604 return CallJsBuiltin(isolate, "ArrayUnshift", args);
583 } 605 }
584 FixedArray* elms = FixedArray::cast(elms_obj); 606 FixedArray* elms = FixedArray::cast(elms_obj);
585 JSArray* array = JSArray::cast(receiver); 607 JSArray* array = JSArray::cast(receiver);
586 ASSERT(array->HasFastElements()); 608 ASSERT(array->HasFastTypeElements());
587 609
588 int len = Smi::cast(array->length())->value(); 610 int len = Smi::cast(array->length())->value();
589 int to_add = args.length() - 1; 611 int to_add = args.length() - 1;
590 int new_length = len + to_add; 612 int new_length = len + to_add;
591 // Currently fixed arrays cannot grow too big, so 613 // Currently fixed arrays cannot grow too big, so
592 // we should never hit this case. 614 // we should never hit this case.
593 ASSERT(to_add <= (Smi::kMaxValue - len)); 615 ASSERT(to_add <= (Smi::kMaxValue - len));
594 616
617 if (FLAG_smi_only_arrays) {
618 MaybeObject* maybe_object =
619 array->EnsureCanContainElements(&args, 1, to_add);
620 if (maybe_object->IsFailure()) return maybe_object;
621 }
622
595 if (new_length > elms->length()) { 623 if (new_length > elms->length()) {
596 // New backing storage is needed. 624 // New backing storage is needed.
597 int capacity = new_length + (new_length >> 1) + 16; 625 int capacity = new_length + (new_length >> 1) + 16;
598 Object* obj; 626 Object* obj;
599 { MaybeObject* maybe_obj = heap->AllocateUninitializedFixedArray(capacity); 627 { MaybeObject* maybe_obj = heap->AllocateUninitializedFixedArray(capacity);
600 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 628 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
601 } 629 }
602 FixedArray* new_elms = FixedArray::cast(obj); 630 FixedArray* new_elms = FixedArray::cast(obj);
603
604 AssertNoAllocation no_gc; 631 AssertNoAllocation no_gc;
605 if (len > 0) { 632 if (len > 0) {
606 CopyElements(heap, &no_gc, new_elms, to_add, elms, 0, len); 633 CopyElements(heap, &no_gc, new_elms, to_add, elms, 0, len);
607 } 634 }
608 FillWithHoles(heap, new_elms, new_length, capacity); 635 FillWithHoles(heap, new_elms, new_length, capacity);
609
610 elms = new_elms; 636 elms = new_elms;
611 array->set_elements(elms); 637 array->set_elements(elms);
612 } else { 638 } else {
613 AssertNoAllocation no_gc; 639 AssertNoAllocation no_gc;
614 MoveElements(heap, &no_gc, elms, to_add, elms, 0, len); 640 MoveElements(heap, &no_gc, elms, to_add, elms, 0, len);
615 } 641 }
616 642
617 // Add the provided values. 643 // Add the provided values.
618 AssertNoAllocation no_gc; 644 AssertNoAllocation no_gc;
619 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); 645 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
620 for (int i = 0; i < to_add; i++) { 646 for (int i = 0; i < to_add; i++) {
621 elms->set(i, args[i + 1], mode); 647 elms->set(i, args[i + 1], mode);
622 } 648 }
623 649
624 // Set the length. 650 // Set the length.
625 array->set_length(Smi::FromInt(new_length)); 651 array->set_length(Smi::FromInt(new_length));
626 return Smi::FromInt(new_length); 652 return Smi::FromInt(new_length);
627 } 653 }
628 654
629 655
630 BUILTIN(ArraySlice) { 656 BUILTIN(ArraySlice) {
631 Heap* heap = isolate->heap(); 657 Heap* heap = isolate->heap();
632 Object* receiver = *args.receiver(); 658 Object* receiver = *args.receiver();
633 FixedArray* elms; 659 FixedArray* elms;
634 int len = -1; 660 int len = -1;
635 if (receiver->IsJSArray()) { 661 if (receiver->IsJSArray()) {
636 JSArray* array = JSArray::cast(receiver); 662 JSArray* array = JSArray::cast(receiver);
637 if (!array->HasFastElements() || 663 if (!array->HasFastTypeElements() ||
638 !IsJSArrayFastElementMovingAllowed(heap, array)) { 664 !IsJSArrayFastElementMovingAllowed(heap, array)) {
639 return CallJsBuiltin(isolate, "ArraySlice", args); 665 return CallJsBuiltin(isolate, "ArraySlice", args);
640 } 666 }
641 667
642 elms = FixedArray::cast(array->elements()); 668 elms = FixedArray::cast(array->elements());
643 len = Smi::cast(array->length())->value(); 669 len = Smi::cast(array->length())->value();
644 } else { 670 } else {
645 // Array.slice(arguments, ...) is quite a common idiom (notably more 671 // Array.slice(arguments, ...) is quite a common idiom (notably more
646 // than 50% of invocations in Web apps). Treat it in C++ as well. 672 // than 50% of invocations in Web apps). Treat it in C++ as well.
647 Map* arguments_map = 673 Map* arguments_map =
648 isolate->context()->global_context()->arguments_boilerplate()->map(); 674 isolate->context()->global_context()->arguments_boilerplate()->map();
649 675
650 bool is_arguments_object_with_fast_elements = 676 bool is_arguments_object_with_fast_elements =
651 receiver->IsJSObject() 677 receiver->IsJSObject()
652 && JSObject::cast(receiver)->map() == arguments_map 678 && JSObject::cast(receiver)->map() == arguments_map
653 && JSObject::cast(receiver)->HasFastElements(); 679 && JSObject::cast(receiver)->HasFastTypeElements();
654 if (!is_arguments_object_with_fast_elements) { 680 if (!is_arguments_object_with_fast_elements) {
655 return CallJsBuiltin(isolate, "ArraySlice", args); 681 return CallJsBuiltin(isolate, "ArraySlice", args);
656 } 682 }
657 elms = FixedArray::cast(JSObject::cast(receiver)->elements()); 683 elms = FixedArray::cast(JSObject::cast(receiver)->elements());
658 Object* len_obj = JSObject::cast(receiver) 684 Object* len_obj = JSObject::cast(receiver)
659 ->InObjectPropertyAt(Heap::kArgumentsLengthIndex); 685 ->InObjectPropertyAt(Heap::kArgumentsLengthIndex);
660 if (!len_obj->IsSmi()) { 686 if (!len_obj->IsSmi()) {
661 return CallJsBuiltin(isolate, "ArraySlice", args); 687 return CallJsBuiltin(isolate, "ArraySlice", args);
662 } 688 }
663 len = Smi::cast(len_obj)->value(); 689 len = Smi::cast(len_obj)->value();
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
714 if (!maybe_result->ToObject(&result)) return maybe_result; 740 if (!maybe_result->ToObject(&result)) return maybe_result;
715 } 741 }
716 JSArray* result_array = JSArray::cast(result); 742 JSArray* result_array = JSArray::cast(result);
717 743
718 { MaybeObject* maybe_result = 744 { MaybeObject* maybe_result =
719 heap->AllocateUninitializedFixedArray(result_len); 745 heap->AllocateUninitializedFixedArray(result_len);
720 if (!maybe_result->ToObject(&result)) return maybe_result; 746 if (!maybe_result->ToObject(&result)) return maybe_result;
721 } 747 }
722 FixedArray* result_elms = FixedArray::cast(result); 748 FixedArray* result_elms = FixedArray::cast(result);
723 749
750 if (FLAG_smi_only_arrays) {
751 MaybeObject* maybe_object =
752 result_array->EnsureCanContainElements(result_elms);
753 if (maybe_object->IsFailure()) return maybe_object;
754 }
755
724 AssertNoAllocation no_gc; 756 AssertNoAllocation no_gc;
725 CopyElements(heap, &no_gc, result_elms, 0, elms, k, result_len); 757 CopyElements(heap, &no_gc, result_elms, 0, elms, k, result_len);
726 758
727 // Set elements. 759 // Set elements.
728 result_array->set_elements(result_elms); 760 result_array->set_elements(result_elms);
729 761
730 // Set the length. 762 // Set the length.
731 result_array->set_length(Smi::FromInt(result_len)); 763 result_array->set_length(Smi::FromInt(result_len));
732 return result_array; 764 return result_array;
733 } 765 }
734 766
735 767
736 BUILTIN(ArraySplice) { 768 BUILTIN(ArraySplice) {
737 Heap* heap = isolate->heap(); 769 Heap* heap = isolate->heap();
738 Object* receiver = *args.receiver(); 770 Object* receiver = *args.receiver();
739 Object* elms_obj; 771 Object* elms_obj;
740 { MaybeObject* maybe_elms_obj = 772 { MaybeObject* maybe_elms_obj =
741 EnsureJSArrayWithWritableFastElements(heap, receiver); 773 EnsureJSArrayWithWritableFastElements(heap, receiver);
742 if (maybe_elms_obj == NULL) 774 if (maybe_elms_obj == NULL)
743 return CallJsBuiltin(isolate, "ArraySplice", args); 775 return CallJsBuiltin(isolate, "ArraySplice", args);
744 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; 776 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
745 } 777 }
746 if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) { 778 if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) {
747 return CallJsBuiltin(isolate, "ArraySplice", args); 779 return CallJsBuiltin(isolate, "ArraySplice", args);
748 } 780 }
749 FixedArray* elms = FixedArray::cast(elms_obj); 781 FixedArray* elms = FixedArray::cast(elms_obj);
750 JSArray* array = JSArray::cast(receiver); 782 JSArray* array = JSArray::cast(receiver);
751 ASSERT(array->HasFastElements()); 783 ASSERT(array->HasFastTypeElements());
752 784
753 int len = Smi::cast(array->length())->value(); 785 int len = Smi::cast(array->length())->value();
754 786
755 int n_arguments = args.length() - 1; 787 int n_arguments = args.length() - 1;
756 788
757 int relative_start = 0; 789 int relative_start = 0;
758 if (n_arguments > 0) { 790 if (n_arguments > 0) {
759 Object* arg1 = args[1]; 791 Object* arg1 = args[1];
760 if (arg1->IsSmi()) { 792 if (arg1->IsSmi()) {
761 relative_start = Smi::cast(arg1)->value(); 793 relative_start = Smi::cast(arg1)->value();
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
819 851
820 // Set elements. 852 // Set elements.
821 result_array->set_elements(result_elms); 853 result_array->set_elements(result_elms);
822 854
823 // Set the length. 855 // Set the length.
824 result_array->set_length(Smi::FromInt(actual_delete_count)); 856 result_array->set_length(Smi::FromInt(actual_delete_count));
825 } 857 }
826 858
827 int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0; 859 int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0;
828 860
861 if (FLAG_smi_only_arrays) {
862 MaybeObject* maybe = array->EnsureCanContainElements(&args, 3, item_count);
863 if (maybe->IsFailure()) return maybe;
864 }
865
829 int new_length = len - actual_delete_count + item_count; 866 int new_length = len - actual_delete_count + item_count;
830 867
868 bool elms_changed = false;
831 if (item_count < actual_delete_count) { 869 if (item_count < actual_delete_count) {
832 // Shrink the array. 870 // Shrink the array.
833 const bool trim_array = !heap->lo_space()->Contains(elms) && 871 const bool trim_array = !heap->lo_space()->Contains(elms) &&
834 ((actual_start + item_count) < 872 ((actual_start + item_count) <
835 (len - actual_delete_count - actual_start)); 873 (len - actual_delete_count - actual_start));
836 if (trim_array) { 874 if (trim_array) {
837 const int delta = actual_delete_count - item_count; 875 const int delta = actual_delete_count - item_count;
838 876
839 if (actual_start > 0) { 877 if (actual_start > 0) {
840 AssertNoAllocation no_gc; 878 AssertNoAllocation no_gc;
841 MoveElements(heap, &no_gc, elms, delta, elms, 0, actual_start); 879 MoveElements(heap, &no_gc, elms, delta, elms, 0, actual_start);
842 } 880 }
843 881
844 elms = LeftTrimFixedArray(heap, elms, delta); 882 elms = LeftTrimFixedArray(heap, elms, delta);
845 array->set_elements(elms, SKIP_WRITE_BARRIER); 883
884 elms_changed = true;
846 } else { 885 } else {
847 AssertNoAllocation no_gc; 886 AssertNoAllocation no_gc;
848 MoveElements(heap, &no_gc, 887 MoveElements(heap, &no_gc,
849 elms, actual_start + item_count, 888 elms, actual_start + item_count,
850 elms, actual_start + actual_delete_count, 889 elms, actual_start + actual_delete_count,
851 (len - actual_delete_count - actual_start)); 890 (len - actual_delete_count - actual_start));
852 FillWithHoles(heap, elms, new_length, len); 891 FillWithHoles(heap, elms, new_length, len);
853 } 892 }
854 } else if (item_count > actual_delete_count) { 893 } else if (item_count > actual_delete_count) {
855 // Currently fixed arrays cannot grow too big, so 894 // Currently fixed arrays cannot grow too big, so
(...skipping 19 matching lines...) Expand all
875 const int to_copy = len - actual_delete_count - actual_start; 914 const int to_copy = len - actual_delete_count - actual_start;
876 if (to_copy > 0) { 915 if (to_copy > 0) {
877 CopyElements(heap, &no_gc, 916 CopyElements(heap, &no_gc,
878 new_elms, actual_start + item_count, 917 new_elms, actual_start + item_count,
879 elms, actual_start + actual_delete_count, 918 elms, actual_start + actual_delete_count,
880 to_copy); 919 to_copy);
881 } 920 }
882 FillWithHoles(heap, new_elms, new_length, capacity); 921 FillWithHoles(heap, new_elms, new_length, capacity);
883 922
884 elms = new_elms; 923 elms = new_elms;
885 array->set_elements(elms); 924 elms_changed = true;
886 } else { 925 } else {
887 AssertNoAllocation no_gc; 926 AssertNoAllocation no_gc;
888 MoveElements(heap, &no_gc, 927 MoveElements(heap, &no_gc,
889 elms, actual_start + item_count, 928 elms, actual_start + item_count,
890 elms, actual_start + actual_delete_count, 929 elms, actual_start + actual_delete_count,
891 (len - actual_delete_count - actual_start)); 930 (len - actual_delete_count - actual_start));
892 } 931 }
893 } 932 }
894 933
895 AssertNoAllocation no_gc; 934 AssertNoAllocation no_gc;
896 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); 935 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
897 for (int k = actual_start; k < actual_start + item_count; k++) { 936 for (int k = actual_start; k < actual_start + item_count; k++) {
898 elms->set(k, args[3 + k - actual_start], mode); 937 elms->set(k, args[3 + k - actual_start], mode);
899 } 938 }
900 939
940 if (elms_changed) {
941 array->set_elements(elms);
942 }
943
901 // Set the length. 944 // Set the length.
902 array->set_length(Smi::FromInt(new_length)); 945 array->set_length(Smi::FromInt(new_length));
903 946
904 return result_array; 947 return result_array;
905 } 948 }
906 949
907 950
908 BUILTIN(ArrayConcat) { 951 BUILTIN(ArrayConcat) {
909 Heap* heap = isolate->heap(); 952 Heap* heap = isolate->heap();
910 Context* global_context = isolate->context()->global_context(); 953 Context* global_context = isolate->context()->global_context();
911 JSObject* array_proto = 954 JSObject* array_proto =
912 JSObject::cast(global_context->array_function()->prototype()); 955 JSObject::cast(global_context->array_function()->prototype());
913 if (!ArrayPrototypeHasNoElements(heap, global_context, array_proto)) { 956 if (!ArrayPrototypeHasNoElements(heap, global_context, array_proto)) {
914 return CallJsBuiltin(isolate, "ArrayConcat", args); 957 return CallJsBuiltin(isolate, "ArrayConcat", args);
915 } 958 }
916 959
917 // Iterate through all the arguments performing checks 960 // Iterate through all the arguments performing checks
918 // and calculating total length. 961 // and calculating total length.
919 int n_arguments = args.length(); 962 int n_arguments = args.length();
920 int result_len = 0; 963 int result_len = 0;
921 for (int i = 0; i < n_arguments; i++) { 964 for (int i = 0; i < n_arguments; i++) {
922 Object* arg = args[i]; 965 Object* arg = args[i];
923 if (!arg->IsJSArray() || !JSArray::cast(arg)->HasFastElements() 966 if (!arg->IsJSArray() || !JSArray::cast(arg)->HasFastTypeElements()
924 || JSArray::cast(arg)->GetPrototype() != array_proto) { 967 || JSArray::cast(arg)->GetPrototype() != array_proto) {
925 return CallJsBuiltin(isolate, "ArrayConcat", args); 968 return CallJsBuiltin(isolate, "ArrayConcat", args);
926 } 969 }
927 970
928 int len = Smi::cast(JSArray::cast(arg)->length())->value(); 971 int len = Smi::cast(JSArray::cast(arg)->length())->value();
929 972
930 // We shouldn't overflow when adding another len. 973 // We shouldn't overflow when adding another len.
931 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); 974 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2);
932 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); 975 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt);
933 USE(kHalfOfMaxInt); 976 USE(kHalfOfMaxInt);
(...skipping 15 matching lines...) Expand all
949 if (!maybe_result->ToObject(&result)) return maybe_result; 992 if (!maybe_result->ToObject(&result)) return maybe_result;
950 } 993 }
951 JSArray* result_array = JSArray::cast(result); 994 JSArray* result_array = JSArray::cast(result);
952 995
953 { MaybeObject* maybe_result = 996 { MaybeObject* maybe_result =
954 heap->AllocateUninitializedFixedArray(result_len); 997 heap->AllocateUninitializedFixedArray(result_len);
955 if (!maybe_result->ToObject(&result)) return maybe_result; 998 if (!maybe_result->ToObject(&result)) return maybe_result;
956 } 999 }
957 FixedArray* result_elms = FixedArray::cast(result); 1000 FixedArray* result_elms = FixedArray::cast(result);
958 1001
1002 if (FLAG_smi_only_arrays) {
1003 for (int i = 0; i < n_arguments; i++) {
1004 JSArray* array = JSArray::cast(args[i]);
1005 int len = Smi::cast(array->length())->value();
1006 if (len > 0) {
1007 FixedArray* elms = FixedArray::cast(array->elements());
1008 MaybeObject* maybe_object =
1009 result_array->EnsureCanContainElements(elms);
1010 if (maybe_object->IsFailure()) return maybe_object;
1011 }
1012 }
1013 }
1014
959 // Copy data. 1015 // Copy data.
960 AssertNoAllocation no_gc; 1016 AssertNoAllocation no_gc;
961 int start_pos = 0; 1017 int start_pos = 0;
962 for (int i = 0; i < n_arguments; i++) { 1018 for (int i = 0; i < n_arguments; i++) {
963 JSArray* array = JSArray::cast(args[i]); 1019 JSArray* array = JSArray::cast(args[i]);
964 int len = Smi::cast(array->length())->value(); 1020 int len = Smi::cast(array->length())->value();
965 if (len > 0) { 1021 if (len > 0) {
966 FixedArray* elms = FixedArray::cast(array->elements()); 1022 FixedArray* elms = FixedArray::cast(array->elements());
967 CopyElements(heap, &no_gc, result_elms, start_pos, elms, 0, len); 1023 CopyElements(heap, &no_gc, result_elms, start_pos, elms, 0, len);
968 start_pos += len; 1024 start_pos += len;
(...skipping 631 matching lines...) Expand 10 before | Expand all | Expand 10 after
1600 ASSERT(!initialized_); 1656 ASSERT(!initialized_);
1601 Isolate* isolate = Isolate::Current(); 1657 Isolate* isolate = Isolate::Current();
1602 Heap* heap = isolate->heap(); 1658 Heap* heap = isolate->heap();
1603 1659
1604 // Create a scope for the handles in the builtins. 1660 // Create a scope for the handles in the builtins.
1605 HandleScope scope(isolate); 1661 HandleScope scope(isolate);
1606 1662
1607 const BuiltinDesc* functions = BuiltinFunctionTable::functions(); 1663 const BuiltinDesc* functions = BuiltinFunctionTable::functions();
1608 1664
1609 // For now we generate builtin adaptor code into a stack-allocated 1665 // For now we generate builtin adaptor code into a stack-allocated
1610 // buffer, before copying it into individual code objects. 1666 // buffer, before copying it into individual code objects. Be careful
1611 byte buffer[4*KB]; 1667 // with alignment, some platforms don't like unaligned code.
1668 union { int force_alignment; byte buffer[4*KB]; } u;
1612 1669
1613 // Traverse the list of builtins and generate an adaptor in a 1670 // Traverse the list of builtins and generate an adaptor in a
1614 // separate code object for each one. 1671 // separate code object for each one.
1615 for (int i = 0; i < builtin_count; i++) { 1672 for (int i = 0; i < builtin_count; i++) {
1616 if (create_heap_objects) { 1673 if (create_heap_objects) {
1617 MacroAssembler masm(isolate, buffer, sizeof buffer); 1674 MacroAssembler masm(isolate, u.buffer, sizeof u.buffer);
1618 // Generate the code/adaptor. 1675 // Generate the code/adaptor.
1619 typedef void (*Generator)(MacroAssembler*, int, BuiltinExtraArguments); 1676 typedef void (*Generator)(MacroAssembler*, int, BuiltinExtraArguments);
1620 Generator g = FUNCTION_CAST<Generator>(functions[i].generator); 1677 Generator g = FUNCTION_CAST<Generator>(functions[i].generator);
1621 // We pass all arguments to the generator, but it may not use all of 1678 // We pass all arguments to the generator, but it may not use all of
1622 // them. This works because the first arguments are on top of the 1679 // them. This works because the first arguments are on top of the
1623 // stack. 1680 // stack.
1681 ASSERT(!masm.has_frame());
1624 g(&masm, functions[i].name, functions[i].extra_args); 1682 g(&masm, functions[i].name, functions[i].extra_args);
1625 // Move the code into the object heap. 1683 // Move the code into the object heap.
1626 CodeDesc desc; 1684 CodeDesc desc;
1627 masm.GetCode(&desc); 1685 masm.GetCode(&desc);
1628 Code::Flags flags = functions[i].flags; 1686 Code::Flags flags = functions[i].flags;
1629 Object* code = NULL; 1687 Object* code = NULL;
1630 { 1688 {
1631 // During startup it's OK to always allocate and defer GC to later. 1689 // During startup it's OK to always allocate and defer GC to later.
1632 // This simplifies things because we don't need to retry. 1690 // This simplifies things because we don't need to retry.
1633 AlwaysAllocateScope __scope__; 1691 AlwaysAllocateScope __scope__;
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1703 return Handle<Code>(code_address); \ 1761 return Handle<Code>(code_address); \
1704 } 1762 }
1705 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) 1763 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
1706 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) 1764 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
1707 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) 1765 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
1708 #undef DEFINE_BUILTIN_ACCESSOR_C 1766 #undef DEFINE_BUILTIN_ACCESSOR_C
1709 #undef DEFINE_BUILTIN_ACCESSOR_A 1767 #undef DEFINE_BUILTIN_ACCESSOR_A
1710 1768
1711 1769
1712 } } // namespace v8::internal 1770 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/bootstrapper.cc ('k') | src/code-stubs.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698