| Index: src/builtins.cc
 | 
| ===================================================================
 | 
| --- src/builtins.cc	(revision 9531)
 | 
| +++ src/builtins.cc	(working copy)
 | 
| @@ -33,6 +33,7 @@
 | 
|  #include "builtins.h"
 | 
|  #include "gdb-jit.h"
 | 
|  #include "ic-inl.h"
 | 
| +#include "mark-compact.h"
 | 
|  #include "vm-state-inl.h"
 | 
|  
 | 
|  namespace v8 {
 | 
| @@ -202,7 +203,7 @@
 | 
|    }
 | 
|  
 | 
|    // 'array' now contains the JSArray we should initialize.
 | 
| -  ASSERT(array->HasFastElements());
 | 
| +  ASSERT(array->HasFastTypeElements());
 | 
|  
 | 
|    // Optimize the case where there is one argument and the argument is a
 | 
|    // small smi.
 | 
| @@ -215,7 +216,8 @@
 | 
|          { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(len);
 | 
|            if (!maybe_obj->ToObject(&obj)) return maybe_obj;
 | 
|          }
 | 
| -        array->SetContent(FixedArray::cast(obj));
 | 
| +        MaybeObject* maybe_obj = array->SetContent(FixedArray::cast(obj));
 | 
| +        if (maybe_obj->IsFailure()) return maybe_obj;
 | 
|          return array;
 | 
|        }
 | 
|      }
 | 
| @@ -239,6 +241,13 @@
 | 
|      if (!maybe_obj->ToObject(&obj)) return maybe_obj;
 | 
|    }
 | 
|  
 | 
| +  // Set length and elements on the array.
 | 
| +  if (FLAG_smi_only_arrays) {
 | 
| +    MaybeObject* maybe_object =
 | 
| +        array->EnsureCanContainElements(FixedArray::cast(obj));
 | 
| +    if (maybe_object->IsFailure()) return maybe_object;
 | 
| +  }
 | 
| +
 | 
|    AssertNoAllocation no_gc;
 | 
|    FixedArray* elms = FixedArray::cast(obj);
 | 
|    WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
 | 
| @@ -247,7 +256,6 @@
 | 
|      elms->set(index, args[index+1], mode);
 | 
|    }
 | 
|  
 | 
| -  // Set length and elements on the array.
 | 
|    array->set_elements(FixedArray::cast(obj));
 | 
|    array->set_length(len);
 | 
|  
 | 
| @@ -295,6 +303,7 @@
 | 
|    if (mode == UPDATE_WRITE_BARRIER) {
 | 
|      heap->RecordWrites(dst->address(), dst->OffsetOfElementAt(dst_index), len);
 | 
|    }
 | 
| +  heap->incremental_marking()->RecordWrites(dst);
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -313,6 +322,7 @@
 | 
|    if (mode == UPDATE_WRITE_BARRIER) {
 | 
|      heap->RecordWrites(dst->address(), dst->OffsetOfElementAt(dst_index), len);
 | 
|    }
 | 
| +  heap->incremental_marking()->RecordWrites(dst);
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -358,6 +368,14 @@
 | 
|    former_start[to_trim] = heap->fixed_array_map();
 | 
|    former_start[to_trim + 1] = Smi::FromInt(len - to_trim);
 | 
|  
 | 
| +  // Maintain marking consistency for HeapObjectIterator and
 | 
| +  // IncrementalMarking.
 | 
| +  int size_delta = to_trim * kPointerSize;
 | 
| +  if (heap->marking()->TransferMark(elms->address(),
 | 
| +                                    elms->address() + size_delta)) {
 | 
| +    MemoryChunk::IncrementLiveBytes(elms->address(), -size_delta);
 | 
| +  }
 | 
| +
 | 
|    return FixedArray::cast(HeapObject::FromAddress(
 | 
|        elms->address() + to_trim * kPointerSize));
 | 
|  }
 | 
| @@ -423,7 +441,7 @@
 | 
|    for (int i = 0; i < n_args; i++) {
 | 
|      argv[i] = args.at<Object>(i + 1).location();
 | 
|    }
 | 
| -  bool pending_exception = false;
 | 
| +  bool pending_exception;
 | 
|    Handle<Object> result = Execution::Call(function,
 | 
|                                            args.receiver(),
 | 
|                                            n_args,
 | 
| @@ -475,9 +493,11 @@
 | 
|      FillWithHoles(heap, new_elms, new_length, capacity);
 | 
|  
 | 
|      elms = new_elms;
 | 
| -    array->set_elements(elms);
 | 
|    }
 | 
|  
 | 
| +  MaybeObject* maybe = array->EnsureCanContainElements(&args, 1, to_add);
 | 
| +  if (maybe->IsFailure()) return maybe;
 | 
| +
 | 
|    // Add the provided values.
 | 
|    AssertNoAllocation no_gc;
 | 
|    WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
 | 
| @@ -485,6 +505,10 @@
 | 
|      elms->set(index + len, args[index + 1], mode);
 | 
|    }
 | 
|  
 | 
| +  if (elms != array->elements()) {
 | 
| +    array->set_elements(elms);
 | 
| +  }
 | 
| +
 | 
|    // Set the length.
 | 
|    array->set_length(Smi::FromInt(new_length));
 | 
|    return Smi::FromInt(new_length);
 | 
| @@ -539,7 +563,7 @@
 | 
|    }
 | 
|    FixedArray* elms = FixedArray::cast(elms_obj);
 | 
|    JSArray* array = JSArray::cast(receiver);
 | 
| -  ASSERT(array->HasFastElements());
 | 
| +  ASSERT(array->HasFastTypeElements());
 | 
|  
 | 
|    int len = Smi::cast(array->length())->value();
 | 
|    if (len == 0) return heap->undefined_value();
 | 
| @@ -551,9 +575,7 @@
 | 
|    }
 | 
|  
 | 
|    if (!heap->lo_space()->Contains(elms)) {
 | 
| -    // As elms still in the same space they used to be,
 | 
| -    // there is no need to update region dirty mark.
 | 
| -    array->set_elements(LeftTrimFixedArray(heap, elms, 1), SKIP_WRITE_BARRIER);
 | 
| +    array->set_elements(LeftTrimFixedArray(heap, elms, 1));
 | 
|    } else {
 | 
|      // Shift the elements.
 | 
|      AssertNoAllocation no_gc;
 | 
| @@ -583,7 +605,7 @@
 | 
|    }
 | 
|    FixedArray* elms = FixedArray::cast(elms_obj);
 | 
|    JSArray* array = JSArray::cast(receiver);
 | 
| -  ASSERT(array->HasFastElements());
 | 
| +  ASSERT(array->HasFastTypeElements());
 | 
|  
 | 
|    int len = Smi::cast(array->length())->value();
 | 
|    int to_add = args.length() - 1;
 | 
| @@ -592,6 +614,12 @@
 | 
|    // we should never hit this case.
 | 
|    ASSERT(to_add <= (Smi::kMaxValue - len));
 | 
|  
 | 
| +  if (FLAG_smi_only_arrays) {
 | 
| +    MaybeObject* maybe_object =
 | 
| +        array->EnsureCanContainElements(&args, 1, to_add);
 | 
| +    if (maybe_object->IsFailure()) return maybe_object;
 | 
| +  }
 | 
| +
 | 
|    if (new_length > elms->length()) {
 | 
|      // New backing storage is needed.
 | 
|      int capacity = new_length + (new_length >> 1) + 16;
 | 
| @@ -600,13 +628,11 @@
 | 
|        if (!maybe_obj->ToObject(&obj)) return maybe_obj;
 | 
|      }
 | 
|      FixedArray* new_elms = FixedArray::cast(obj);
 | 
| -
 | 
|      AssertNoAllocation no_gc;
 | 
|      if (len > 0) {
 | 
|        CopyElements(heap, &no_gc, new_elms, to_add, elms, 0, len);
 | 
|      }
 | 
|      FillWithHoles(heap, new_elms, new_length, capacity);
 | 
| -
 | 
|      elms = new_elms;
 | 
|      array->set_elements(elms);
 | 
|    } else {
 | 
| @@ -634,7 +660,7 @@
 | 
|    int len = -1;
 | 
|    if (receiver->IsJSArray()) {
 | 
|      JSArray* array = JSArray::cast(receiver);
 | 
| -    if (!array->HasFastElements() ||
 | 
| +    if (!array->HasFastTypeElements() ||
 | 
|          !IsJSArrayFastElementMovingAllowed(heap, array)) {
 | 
|        return CallJsBuiltin(isolate, "ArraySlice", args);
 | 
|      }
 | 
| @@ -650,7 +676,7 @@
 | 
|      bool is_arguments_object_with_fast_elements =
 | 
|          receiver->IsJSObject()
 | 
|          && JSObject::cast(receiver)->map() == arguments_map
 | 
| -        && JSObject::cast(receiver)->HasFastElements();
 | 
| +        && JSObject::cast(receiver)->HasFastTypeElements();
 | 
|      if (!is_arguments_object_with_fast_elements) {
 | 
|        return CallJsBuiltin(isolate, "ArraySlice", args);
 | 
|      }
 | 
| @@ -721,6 +747,12 @@
 | 
|    }
 | 
|    FixedArray* result_elms = FixedArray::cast(result);
 | 
|  
 | 
| +  if (FLAG_smi_only_arrays) {
 | 
| +    MaybeObject* maybe_object =
 | 
| +        result_array->EnsureCanContainElements(result_elms);
 | 
| +    if (maybe_object->IsFailure()) return maybe_object;
 | 
| +  }
 | 
| +
 | 
|    AssertNoAllocation no_gc;
 | 
|    CopyElements(heap, &no_gc, result_elms, 0, elms, k, result_len);
 | 
|  
 | 
| @@ -748,7 +780,7 @@
 | 
|    }
 | 
|    FixedArray* elms = FixedArray::cast(elms_obj);
 | 
|    JSArray* array = JSArray::cast(receiver);
 | 
| -  ASSERT(array->HasFastElements());
 | 
| +  ASSERT(array->HasFastTypeElements());
 | 
|  
 | 
|    int len = Smi::cast(array->length())->value();
 | 
|  
 | 
| @@ -826,8 +858,14 @@
 | 
|  
 | 
|    int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0;
 | 
|  
 | 
| +  if (FLAG_smi_only_arrays) {
 | 
| +    MaybeObject* maybe = array->EnsureCanContainElements(&args, 3, item_count);
 | 
| +    if (maybe->IsFailure()) return maybe;
 | 
| +  }
 | 
| +
 | 
|    int new_length = len - actual_delete_count + item_count;
 | 
|  
 | 
| +  bool elms_changed = false;
 | 
|    if (item_count < actual_delete_count) {
 | 
|      // Shrink the array.
 | 
|      const bool trim_array = !heap->lo_space()->Contains(elms) &&
 | 
| @@ -842,7 +880,8 @@
 | 
|        }
 | 
|  
 | 
|        elms = LeftTrimFixedArray(heap, elms, delta);
 | 
| -      array->set_elements(elms, SKIP_WRITE_BARRIER);
 | 
| +
 | 
| +      elms_changed = true;
 | 
|      } else {
 | 
|        AssertNoAllocation no_gc;
 | 
|        MoveElements(heap, &no_gc,
 | 
| @@ -882,7 +921,7 @@
 | 
|        FillWithHoles(heap, new_elms, new_length, capacity);
 | 
|  
 | 
|        elms = new_elms;
 | 
| -      array->set_elements(elms);
 | 
| +      elms_changed = true;
 | 
|      } else {
 | 
|        AssertNoAllocation no_gc;
 | 
|        MoveElements(heap, &no_gc,
 | 
| @@ -898,6 +937,10 @@
 | 
|      elms->set(k, args[3 + k - actual_start], mode);
 | 
|    }
 | 
|  
 | 
| +  if (elms_changed) {
 | 
| +    array->set_elements(elms);
 | 
| +  }
 | 
| +
 | 
|    // Set the length.
 | 
|    array->set_length(Smi::FromInt(new_length));
 | 
|  
 | 
| @@ -920,7 +963,7 @@
 | 
|    int result_len = 0;
 | 
|    for (int i = 0; i < n_arguments; i++) {
 | 
|      Object* arg = args[i];
 | 
| -    if (!arg->IsJSArray() || !JSArray::cast(arg)->HasFastElements()
 | 
| +    if (!arg->IsJSArray() || !JSArray::cast(arg)->HasFastTypeElements()
 | 
|          || JSArray::cast(arg)->GetPrototype() != array_proto) {
 | 
|        return CallJsBuiltin(isolate, "ArrayConcat", args);
 | 
|      }
 | 
| @@ -956,6 +999,19 @@
 | 
|    }
 | 
|    FixedArray* result_elms = FixedArray::cast(result);
 | 
|  
 | 
| +  if (FLAG_smi_only_arrays) {
 | 
| +    for (int i = 0; i < n_arguments; i++) {
 | 
| +      JSArray* array = JSArray::cast(args[i]);
 | 
| +      int len = Smi::cast(array->length())->value();
 | 
| +      if (len > 0) {
 | 
| +        FixedArray* elms = FixedArray::cast(array->elements());
 | 
| +        MaybeObject* maybe_object =
 | 
| +            result_array->EnsureCanContainElements(elms);
 | 
| +        if (maybe_object->IsFailure()) return maybe_object;
 | 
| +      }
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
|    // Copy data.
 | 
|    AssertNoAllocation no_gc;
 | 
|    int start_pos = 0;
 | 
| @@ -1607,20 +1663,22 @@
 | 
|    const BuiltinDesc* functions = BuiltinFunctionTable::functions();
 | 
|  
 | 
|    // For now we generate builtin adaptor code into a stack-allocated
 | 
| -  // buffer, before copying it into individual code objects.
 | 
| -  byte buffer[4*KB];
 | 
| +  // buffer, before copying it into individual code objects. Be careful
 | 
| +  // with alignment, some platforms don't like unaligned code.
 | 
| +  union { int force_alignment; byte buffer[4*KB]; } u;
 | 
|  
 | 
|    // Traverse the list of builtins and generate an adaptor in a
 | 
|    // separate code object for each one.
 | 
|    for (int i = 0; i < builtin_count; i++) {
 | 
|      if (create_heap_objects) {
 | 
| -      MacroAssembler masm(isolate, buffer, sizeof buffer);
 | 
| +      MacroAssembler masm(isolate, u.buffer, sizeof u.buffer);
 | 
|        // Generate the code/adaptor.
 | 
|        typedef void (*Generator)(MacroAssembler*, int, BuiltinExtraArguments);
 | 
|        Generator g = FUNCTION_CAST<Generator>(functions[i].generator);
 | 
|        // We pass all arguments to the generator, but it may not use all of
 | 
|        // them.  This works because the first arguments are on top of the
 | 
|        // stack.
 | 
| +      ASSERT(!masm.has_frame());
 | 
|        g(&masm, functions[i].name, functions[i].extra_args);
 | 
|        // Move the code into the object heap.
 | 
|        CodeDesc desc;
 | 
| 
 |