Index: src/builtins.cc |
=================================================================== |
--- src/builtins.cc (revision 7267) |
+++ src/builtins.cc (working copy) |
@@ -107,7 +107,6 @@ |
} // namespace |
- |
// ---------------------------------------------------------------------------- |
// Support macro for defining builtins in C++. |
// ---------------------------------------------------------------------------- |
@@ -123,26 +122,27 @@ |
#ifdef DEBUG |
-#define BUILTIN(name) \ |
- MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name( \ |
- name##ArgumentsType args); \ |
- MUST_USE_RESULT static MaybeObject* Builtin_##name( \ |
- name##ArgumentsType args) { \ |
- args.Verify(); \ |
- return Builtin_Impl_##name(args); \ |
- } \ |
- MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name( \ |
- name##ArgumentsType args) |
+#define BUILTIN(name) \ |
+ MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name( \ |
+ name##ArgumentsType args, Isolate* isolate); \ |
+ MUST_USE_RESULT static MaybeObject* Builtin_##name( \ |
+ name##ArgumentsType args, Isolate* isolate) { \ |
+ ASSERT(isolate == Isolate::Current()); \ |
+ args.Verify(); \ |
+ return Builtin_Impl_##name(args, isolate); \ |
+ } \ |
+ MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name( \ |
+ name##ArgumentsType args, Isolate* isolate) |
#else // For release mode. |
-#define BUILTIN(name) \ |
- static MaybeObject* Builtin_##name(name##ArgumentsType args) |
+#define BUILTIN(name) \ |
+ static MaybeObject* Builtin_##name(name##ArgumentsType args, Isolate* isolate) |
#endif |
-static inline bool CalledAsConstructor() { |
+static inline bool CalledAsConstructor(Isolate* isolate) { |
#ifdef DEBUG |
// Calculate the result using a full stack frame iterator and check |
// that the state of the stack is as we assume it to be in the |
@@ -153,7 +153,7 @@ |
StackFrame* frame = it.frame(); |
bool reference_result = frame->is_construct(); |
#endif |
- Address fp = Top::c_entry_fp(Top::GetCurrentThread()); |
+ Address fp = Isolate::c_entry_fp(isolate->thread_local_top()); |
// Because we know fp points to an exit frame we can use the relevant |
// part of ExitFrame::ComputeCallerState directly. |
const int kCallerOffset = ExitFrameConstants::kCallerFPOffset; |
@@ -172,30 +172,30 @@ |
// ---------------------------------------------------------------------------- |
- |
BUILTIN(Illegal) { |
UNREACHABLE(); |
- return Heap::undefined_value(); // Make compiler happy. |
+ return isolate->heap()->undefined_value(); // Make compiler happy. |
} |
BUILTIN(EmptyFunction) { |
- return Heap::undefined_value(); |
+ return isolate->heap()->undefined_value(); |
} |
BUILTIN(ArrayCodeGeneric) { |
- Counters::array_function_runtime.Increment(); |
+ Heap* heap = isolate->heap(); |
+ isolate->counters()->array_function_runtime()->Increment(); |
JSArray* array; |
- if (CalledAsConstructor()) { |
+ if (CalledAsConstructor(isolate)) { |
array = JSArray::cast(*args.receiver()); |
} else { |
// Allocate the JS Array |
JSFunction* constructor = |
- Top::context()->global_context()->array_function(); |
+ isolate->context()->global_context()->array_function(); |
Object* obj; |
- { MaybeObject* maybe_obj = Heap::AllocateJSObject(constructor); |
+ { MaybeObject* maybe_obj = heap->AllocateJSObject(constructor); |
if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
} |
array = JSArray::cast(obj); |
@@ -212,7 +212,7 @@ |
int len = Smi::cast(obj)->value(); |
if (len >= 0 && len < JSObject::kInitialMaxFastElementArray) { |
Object* obj; |
- { MaybeObject* maybe_obj = Heap::AllocateFixedArrayWithHoles(len); |
+ { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(len); |
if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
} |
array->SetContent(FixedArray::cast(obj)); |
@@ -235,7 +235,7 @@ |
int number_of_elements = args.length() - 1; |
Smi* len = Smi::FromInt(number_of_elements); |
Object* obj; |
- { MaybeObject* maybe_obj = Heap::AllocateFixedArrayWithHoles(len->value()); |
+ { MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(len->value()); |
if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
} |
@@ -255,77 +255,81 @@ |
} |
-MUST_USE_RESULT static MaybeObject* AllocateJSArray() { |
+MUST_USE_RESULT static MaybeObject* AllocateJSArray(Heap* heap) { |
JSFunction* array_function = |
- Top::context()->global_context()->array_function(); |
+ heap->isolate()->context()->global_context()->array_function(); |
Object* result; |
- { MaybeObject* maybe_result = Heap::AllocateJSObject(array_function); |
+ { MaybeObject* maybe_result = heap->AllocateJSObject(array_function); |
if (!maybe_result->ToObject(&result)) return maybe_result; |
} |
return result; |
} |
-MUST_USE_RESULT static MaybeObject* AllocateEmptyJSArray() { |
+MUST_USE_RESULT static MaybeObject* AllocateEmptyJSArray(Heap* heap) { |
Object* result; |
- { MaybeObject* maybe_result = AllocateJSArray(); |
+ { MaybeObject* maybe_result = AllocateJSArray(heap); |
if (!maybe_result->ToObject(&result)) return maybe_result; |
} |
JSArray* result_array = JSArray::cast(result); |
result_array->set_length(Smi::FromInt(0)); |
- result_array->set_elements(Heap::empty_fixed_array()); |
+ result_array->set_elements(heap->empty_fixed_array()); |
return result_array; |
} |
-static void CopyElements(AssertNoAllocation* no_gc, |
+static void CopyElements(Heap* heap, |
+ AssertNoAllocation* no_gc, |
FixedArray* dst, |
int dst_index, |
FixedArray* src, |
int src_index, |
int len) { |
ASSERT(dst != src); // Use MoveElements instead. |
- ASSERT(dst->map() != Heap::fixed_cow_array_map()); |
+ ASSERT(dst->map() != HEAP->fixed_cow_array_map()); |
ASSERT(len > 0); |
CopyWords(dst->data_start() + dst_index, |
src->data_start() + src_index, |
len); |
WriteBarrierMode mode = dst->GetWriteBarrierMode(*no_gc); |
if (mode == UPDATE_WRITE_BARRIER) { |
- Heap::RecordWrites(dst->address(), dst->OffsetOfElementAt(dst_index), len); |
+ heap->RecordWrites(dst->address(), dst->OffsetOfElementAt(dst_index), len); |
} |
} |
-static void MoveElements(AssertNoAllocation* no_gc, |
+static void MoveElements(Heap* heap, |
+ AssertNoAllocation* no_gc, |
FixedArray* dst, |
int dst_index, |
FixedArray* src, |
int src_index, |
int len) { |
- ASSERT(dst->map() != Heap::fixed_cow_array_map()); |
+ ASSERT(dst->map() != HEAP->fixed_cow_array_map()); |
memmove(dst->data_start() + dst_index, |
src->data_start() + src_index, |
len * kPointerSize); |
WriteBarrierMode mode = dst->GetWriteBarrierMode(*no_gc); |
if (mode == UPDATE_WRITE_BARRIER) { |
- Heap::RecordWrites(dst->address(), dst->OffsetOfElementAt(dst_index), len); |
+ heap->RecordWrites(dst->address(), dst->OffsetOfElementAt(dst_index), len); |
} |
} |
-static void FillWithHoles(FixedArray* dst, int from, int to) { |
- ASSERT(dst->map() != Heap::fixed_cow_array_map()); |
- MemsetPointer(dst->data_start() + from, Heap::the_hole_value(), to - from); |
+static void FillWithHoles(Heap* heap, FixedArray* dst, int from, int to) { |
+ ASSERT(dst->map() != heap->fixed_cow_array_map()); |
+ MemsetPointer(dst->data_start() + from, heap->the_hole_value(), to - from); |
} |
-static FixedArray* LeftTrimFixedArray(FixedArray* elms, int to_trim) { |
- ASSERT(elms->map() != Heap::fixed_cow_array_map()); |
+static FixedArray* LeftTrimFixedArray(Heap* heap, |
+ FixedArray* elms, |
+ int to_trim) { |
+ ASSERT(elms->map() != HEAP->fixed_cow_array_map()); |
// For now this trick is only applied to fixed arrays in new and paged space. |
// In large object space the object's start must coincide with chunk |
// and thus the trick is just not applicable. |
- ASSERT(!Heap::lo_space()->Contains(elms)); |
+ ASSERT(!HEAP->lo_space()->Contains(elms)); |
STATIC_ASSERT(FixedArray::kMapOffset == 0); |
STATIC_ASSERT(FixedArray::kLengthOffset == kPointerSize); |
@@ -336,7 +340,7 @@ |
const int len = elms->length(); |
if (to_trim > FixedArray::kHeaderSize / kPointerSize && |
- !Heap::new_space()->Contains(elms)) { |
+ !heap->new_space()->Contains(elms)) { |
// If we are doing a big trim in old space then we zap the space that was |
// formerly part of the array so that the GC (aided by the card-based |
// remembered set) won't find pointers to new-space there. |
@@ -349,9 +353,9 @@ |
// Technically in new space this write might be omitted (except for |
// debug mode which iterates through the heap), but to play safer |
// we still do it. |
- Heap::CreateFillerObjectAt(elms->address(), to_trim * kPointerSize); |
+ heap->CreateFillerObjectAt(elms->address(), to_trim * kPointerSize); |
- former_start[to_trim] = Heap::fixed_array_map(); |
+ former_start[to_trim] = heap->fixed_array_map(); |
former_start[to_trim + 1] = Smi::FromInt(len - to_trim); |
return FixedArray::cast(HeapObject::FromAddress( |
@@ -359,20 +363,21 @@ |
} |
-static bool ArrayPrototypeHasNoElements(Context* global_context, |
+static bool ArrayPrototypeHasNoElements(Heap* heap, |
+ Context* global_context, |
JSObject* array_proto) { |
// This method depends on non writability of Object and Array prototype |
// fields. |
- if (array_proto->elements() != Heap::empty_fixed_array()) return false; |
+ if (array_proto->elements() != heap->empty_fixed_array()) return false; |
// Hidden prototype |
array_proto = JSObject::cast(array_proto->GetPrototype()); |
- ASSERT(array_proto->elements() == Heap::empty_fixed_array()); |
+ ASSERT(array_proto->elements() == heap->empty_fixed_array()); |
// Object.prototype |
Object* proto = array_proto->GetPrototype(); |
- if (proto == Heap::null_value()) return false; |
+ if (proto == heap->null_value()) return false; |
array_proto = JSObject::cast(proto); |
if (array_proto != global_context->initial_object_prototype()) return false; |
- if (array_proto->elements() != Heap::empty_fixed_array()) return false; |
+ if (array_proto->elements() != heap->empty_fixed_array()) return false; |
ASSERT(array_proto->GetPrototype()->IsNull()); |
return true; |
} |
@@ -380,35 +385,38 @@ |
MUST_USE_RESULT |
static inline MaybeObject* EnsureJSArrayWithWritableFastElements( |
- Object* receiver) { |
+ Heap* heap, Object* receiver) { |
if (!receiver->IsJSArray()) return NULL; |
JSArray* array = JSArray::cast(receiver); |
HeapObject* elms = array->elements(); |
- if (elms->map() == Heap::fixed_array_map()) return elms; |
- if (elms->map() == Heap::fixed_cow_array_map()) { |
+ if (elms->map() == heap->fixed_array_map()) return elms; |
+ if (elms->map() == heap->fixed_cow_array_map()) { |
return array->EnsureWritableFastElements(); |
} |
return NULL; |
} |
-static inline bool IsJSArrayFastElementMovingAllowed(JSArray* receiver) { |
- Context* global_context = Top::context()->global_context(); |
+static inline bool IsJSArrayFastElementMovingAllowed(Heap* heap, |
+ JSArray* receiver) { |
+ Context* global_context = heap->isolate()->context()->global_context(); |
JSObject* array_proto = |
JSObject::cast(global_context->array_function()->prototype()); |
return receiver->GetPrototype() == array_proto && |
- ArrayPrototypeHasNoElements(global_context, array_proto); |
+ ArrayPrototypeHasNoElements(heap, global_context, array_proto); |
} |
MUST_USE_RESULT static MaybeObject* CallJsBuiltin( |
+ Isolate* isolate, |
const char* name, |
BuiltinArguments<NO_EXTRA_ARGUMENTS> args) { |
- HandleScope handleScope; |
+ HandleScope handleScope(isolate); |
Handle<Object> js_builtin = |
- GetProperty(Handle<JSObject>(Top::global_context()->builtins()), |
- name); |
+ GetProperty(Handle<JSObject>( |
+ isolate->global_context()->builtins()), |
+ name); |
ASSERT(js_builtin->IsJSFunction()); |
Handle<JSFunction> function(Handle<JSFunction>::cast(js_builtin)); |
ScopedVector<Object**> argv(args.length() - 1); |
@@ -428,11 +436,14 @@ |
BUILTIN(ArrayPush) { |
+ Heap* heap = isolate->heap(); |
Object* receiver = *args.receiver(); |
Object* elms_obj; |
{ MaybeObject* maybe_elms_obj = |
- EnsureJSArrayWithWritableFastElements(receiver); |
- if (maybe_elms_obj == NULL) return CallJsBuiltin("ArrayPush", args); |
+ EnsureJSArrayWithWritableFastElements(heap, receiver); |
+ if (maybe_elms_obj == NULL) { |
+ return CallJsBuiltin(isolate, "ArrayPush", args); |
+ } |
if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; |
} |
FixedArray* elms = FixedArray::cast(elms_obj); |
@@ -453,16 +464,16 @@ |
// New backing storage is needed. |
int capacity = new_length + (new_length >> 1) + 16; |
Object* obj; |
- { MaybeObject* maybe_obj = Heap::AllocateUninitializedFixedArray(capacity); |
+ { MaybeObject* maybe_obj = heap->AllocateUninitializedFixedArray(capacity); |
if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
} |
FixedArray* new_elms = FixedArray::cast(obj); |
AssertNoAllocation no_gc; |
if (len > 0) { |
- CopyElements(&no_gc, new_elms, 0, elms, 0, len); |
+ CopyElements(heap, &no_gc, new_elms, 0, elms, 0, len); |
} |
- FillWithHoles(new_elms, new_length, capacity); |
+ FillWithHoles(heap, new_elms, new_length, capacity); |
elms = new_elms; |
array->set_elements(elms); |
@@ -482,18 +493,19 @@ |
BUILTIN(ArrayPop) { |
+ Heap* heap = isolate->heap(); |
Object* receiver = *args.receiver(); |
Object* elms_obj; |
{ MaybeObject* maybe_elms_obj = |
- EnsureJSArrayWithWritableFastElements(receiver); |
- if (maybe_elms_obj == NULL) return CallJsBuiltin("ArrayPop", args); |
+ EnsureJSArrayWithWritableFastElements(heap, receiver); |
+ if (maybe_elms_obj == NULL) return CallJsBuiltin(isolate, "ArrayPop", args); |
if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; |
} |
FixedArray* elms = FixedArray::cast(elms_obj); |
JSArray* array = JSArray::cast(receiver); |
int len = Smi::cast(array->length())->value(); |
- if (len == 0) return Heap::undefined_value(); |
+ if (len == 0) return heap->undefined_value(); |
// Get top element |
MaybeObject* top = elms->get(len - 1); |
@@ -514,38 +526,40 @@ |
BUILTIN(ArrayShift) { |
+ Heap* heap = isolate->heap(); |
Object* receiver = *args.receiver(); |
Object* elms_obj; |
{ MaybeObject* maybe_elms_obj = |
- EnsureJSArrayWithWritableFastElements(receiver); |
- if (maybe_elms_obj == NULL) return CallJsBuiltin("ArrayShift", args); |
+ EnsureJSArrayWithWritableFastElements(heap, receiver); |
+ if (maybe_elms_obj == NULL) |
+ return CallJsBuiltin(isolate, "ArrayShift", args); |
if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; |
} |
- if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) { |
- return CallJsBuiltin("ArrayShift", args); |
+ if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) { |
+ return CallJsBuiltin(isolate, "ArrayShift", args); |
} |
FixedArray* elms = FixedArray::cast(elms_obj); |
JSArray* array = JSArray::cast(receiver); |
ASSERT(array->HasFastElements()); |
int len = Smi::cast(array->length())->value(); |
- if (len == 0) return Heap::undefined_value(); |
+ if (len == 0) return heap->undefined_value(); |
// Get first element |
Object* first = elms->get(0); |
if (first->IsTheHole()) { |
- first = Heap::undefined_value(); |
+ first = heap->undefined_value(); |
} |
- if (!Heap::lo_space()->Contains(elms)) { |
+ 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(elms, 1), SKIP_WRITE_BARRIER); |
+ array->set_elements(LeftTrimFixedArray(heap, elms, 1), SKIP_WRITE_BARRIER); |
} else { |
// Shift the elements. |
AssertNoAllocation no_gc; |
- MoveElements(&no_gc, elms, 0, elms, 1, len - 1); |
- elms->set(len - 1, Heap::the_hole_value()); |
+ MoveElements(heap, &no_gc, elms, 0, elms, 1, len - 1); |
+ elms->set(len - 1, heap->the_hole_value()); |
} |
// Set the length. |
@@ -556,15 +570,17 @@ |
BUILTIN(ArrayUnshift) { |
+ Heap* heap = isolate->heap(); |
Object* receiver = *args.receiver(); |
Object* elms_obj; |
{ MaybeObject* maybe_elms_obj = |
- EnsureJSArrayWithWritableFastElements(receiver); |
- if (maybe_elms_obj == NULL) return CallJsBuiltin("ArrayUnshift", args); |
+ EnsureJSArrayWithWritableFastElements(heap, receiver); |
+ if (maybe_elms_obj == NULL) |
+ return CallJsBuiltin(isolate, "ArrayUnshift", args); |
if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; |
} |
- if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) { |
- return CallJsBuiltin("ArrayUnshift", args); |
+ if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) { |
+ return CallJsBuiltin(isolate, "ArrayUnshift", args); |
} |
FixedArray* elms = FixedArray::cast(elms_obj); |
JSArray* array = JSArray::cast(receiver); |
@@ -581,22 +597,22 @@ |
// New backing storage is needed. |
int capacity = new_length + (new_length >> 1) + 16; |
Object* obj; |
- { MaybeObject* maybe_obj = Heap::AllocateUninitializedFixedArray(capacity); |
+ { MaybeObject* maybe_obj = heap->AllocateUninitializedFixedArray(capacity); |
if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
} |
FixedArray* new_elms = FixedArray::cast(obj); |
AssertNoAllocation no_gc; |
if (len > 0) { |
- CopyElements(&no_gc, new_elms, to_add, elms, 0, len); |
+ CopyElements(heap, &no_gc, new_elms, to_add, elms, 0, len); |
} |
- FillWithHoles(new_elms, new_length, capacity); |
+ FillWithHoles(heap, new_elms, new_length, capacity); |
elms = new_elms; |
array->set_elements(elms); |
} else { |
AssertNoAllocation no_gc; |
- MoveElements(&no_gc, elms, to_add, elms, 0, len); |
+ MoveElements(heap, &no_gc, elms, to_add, elms, 0, len); |
} |
// Add the provided values. |
@@ -613,14 +629,15 @@ |
BUILTIN(ArraySlice) { |
+ Heap* heap = isolate->heap(); |
Object* receiver = *args.receiver(); |
FixedArray* elms; |
int len = -1; |
if (receiver->IsJSArray()) { |
JSArray* array = JSArray::cast(receiver); |
if (!array->HasFastElements() || |
- !IsJSArrayFastElementMovingAllowed(array)) { |
- return CallJsBuiltin("ArraySlice", args); |
+ !IsJSArrayFastElementMovingAllowed(heap, array)) { |
+ return CallJsBuiltin(isolate, "ArraySlice", args); |
} |
elms = FixedArray::cast(array->elements()); |
@@ -629,28 +646,28 @@ |
// Array.slice(arguments, ...) is quite a common idiom (notably more |
// than 50% of invocations in Web apps). Treat it in C++ as well. |
Map* arguments_map = |
- Top::context()->global_context()->arguments_boilerplate()->map(); |
+ isolate->context()->global_context()->arguments_boilerplate()->map(); |
bool is_arguments_object_with_fast_elements = |
receiver->IsJSObject() |
&& JSObject::cast(receiver)->map() == arguments_map |
&& JSObject::cast(receiver)->HasFastElements(); |
if (!is_arguments_object_with_fast_elements) { |
- return CallJsBuiltin("ArraySlice", args); |
+ return CallJsBuiltin(isolate, "ArraySlice", args); |
} |
elms = FixedArray::cast(JSObject::cast(receiver)->elements()); |
Object* len_obj = JSObject::cast(receiver) |
->InObjectPropertyAt(Heap::kArgumentsLengthIndex); |
if (!len_obj->IsSmi()) { |
- return CallJsBuiltin("ArraySlice", args); |
+ return CallJsBuiltin(isolate, "ArraySlice", args); |
} |
len = Smi::cast(len_obj)->value(); |
if (len > elms->length()) { |
- return CallJsBuiltin("ArraySlice", args); |
+ return CallJsBuiltin(isolate, "ArraySlice", args); |
} |
for (int i = 0; i < len; i++) { |
- if (elms->get(i) == Heap::the_hole_value()) { |
- return CallJsBuiltin("ArraySlice", args); |
+ if (elms->get(i) == heap->the_hole_value()) { |
+ return CallJsBuiltin(isolate, "ArraySlice", args); |
} |
} |
} |
@@ -667,14 +684,14 @@ |
if (arg1->IsSmi()) { |
relative_start = Smi::cast(arg1)->value(); |
} else if (!arg1->IsUndefined()) { |
- return CallJsBuiltin("ArraySlice", args); |
+ return CallJsBuiltin(isolate, "ArraySlice", args); |
} |
if (n_arguments > 1) { |
Object* arg2 = args[2]; |
if (arg2->IsSmi()) { |
relative_end = Smi::cast(arg2)->value(); |
} else if (!arg2->IsUndefined()) { |
- return CallJsBuiltin("ArraySlice", args); |
+ return CallJsBuiltin(isolate, "ArraySlice", args); |
} |
} |
} |
@@ -690,23 +707,23 @@ |
// Calculate the length of result array. |
int result_len = final - k; |
if (result_len <= 0) { |
- return AllocateEmptyJSArray(); |
+ return AllocateEmptyJSArray(heap); |
} |
Object* result; |
- { MaybeObject* maybe_result = AllocateJSArray(); |
+ { MaybeObject* maybe_result = AllocateJSArray(heap); |
if (!maybe_result->ToObject(&result)) return maybe_result; |
} |
JSArray* result_array = JSArray::cast(result); |
{ MaybeObject* maybe_result = |
- Heap::AllocateUninitializedFixedArray(result_len); |
+ heap->AllocateUninitializedFixedArray(result_len); |
if (!maybe_result->ToObject(&result)) return maybe_result; |
} |
FixedArray* result_elms = FixedArray::cast(result); |
AssertNoAllocation no_gc; |
- CopyElements(&no_gc, result_elms, 0, elms, k, result_len); |
+ CopyElements(heap, &no_gc, result_elms, 0, elms, k, result_len); |
// Set elements. |
result_array->set_elements(result_elms); |
@@ -718,15 +735,17 @@ |
BUILTIN(ArraySplice) { |
+ Heap* heap = isolate->heap(); |
Object* receiver = *args.receiver(); |
Object* elms_obj; |
{ MaybeObject* maybe_elms_obj = |
- EnsureJSArrayWithWritableFastElements(receiver); |
- if (maybe_elms_obj == NULL) return CallJsBuiltin("ArraySplice", args); |
+ EnsureJSArrayWithWritableFastElements(heap, receiver); |
+ if (maybe_elms_obj == NULL) |
+ return CallJsBuiltin(isolate, "ArraySplice", args); |
if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; |
} |
- if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) { |
- return CallJsBuiltin("ArraySplice", args); |
+ if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) { |
+ return CallJsBuiltin(isolate, "ArraySplice", args); |
} |
FixedArray* elms = FixedArray::cast(elms_obj); |
JSArray* array = JSArray::cast(receiver); |
@@ -742,7 +761,7 @@ |
if (arg1->IsSmi()) { |
relative_start = Smi::cast(arg1)->value(); |
} else if (!arg1->IsUndefined()) { |
- return CallJsBuiltin("ArraySplice", args); |
+ return CallJsBuiltin(isolate, "ArraySplice", args); |
} |
} |
int actual_start = (relative_start < 0) ? Max(len + relative_start, 0) |
@@ -764,7 +783,7 @@ |
if (arg2->IsSmi()) { |
value = Smi::cast(arg2)->value(); |
} else { |
- return CallJsBuiltin("ArraySplice", args); |
+ return CallJsBuiltin(isolate, "ArraySplice", args); |
} |
} |
actual_delete_count = Min(Max(value, 0), len - actual_start); |
@@ -773,27 +792,28 @@ |
JSArray* result_array = NULL; |
if (actual_delete_count == 0) { |
Object* result; |
- { MaybeObject* maybe_result = AllocateEmptyJSArray(); |
+ { MaybeObject* maybe_result = AllocateEmptyJSArray(heap); |
if (!maybe_result->ToObject(&result)) return maybe_result; |
} |
result_array = JSArray::cast(result); |
} else { |
// Allocate result array. |
Object* result; |
- { MaybeObject* maybe_result = AllocateJSArray(); |
+ { MaybeObject* maybe_result = AllocateJSArray(heap); |
if (!maybe_result->ToObject(&result)) return maybe_result; |
} |
result_array = JSArray::cast(result); |
{ MaybeObject* maybe_result = |
- Heap::AllocateUninitializedFixedArray(actual_delete_count); |
+ heap->AllocateUninitializedFixedArray(actual_delete_count); |
if (!maybe_result->ToObject(&result)) return maybe_result; |
} |
FixedArray* result_elms = FixedArray::cast(result); |
AssertNoAllocation no_gc; |
// Fill newly created array. |
- CopyElements(&no_gc, |
+ CopyElements(heap, |
+ &no_gc, |
result_elms, 0, |
elms, actual_start, |
actual_delete_count); |
@@ -811,7 +831,7 @@ |
if (item_count < actual_delete_count) { |
// Shrink the array. |
- const bool trim_array = !Heap::lo_space()->Contains(elms) && |
+ const bool trim_array = !heap->lo_space()->Contains(elms) && |
((actual_start + item_count) < |
(len - actual_delete_count - actual_start)); |
if (trim_array) { |
@@ -822,15 +842,15 @@ |
memmove(start + delta, start, actual_start * kPointerSize); |
} |
- elms = LeftTrimFixedArray(elms, delta); |
+ elms = LeftTrimFixedArray(heap, elms, delta); |
array->set_elements(elms, SKIP_WRITE_BARRIER); |
} else { |
AssertNoAllocation no_gc; |
- MoveElements(&no_gc, |
+ MoveElements(heap, &no_gc, |
elms, actual_start + item_count, |
elms, actual_start + actual_delete_count, |
(len - actual_delete_count - actual_start)); |
- FillWithHoles(elms, new_length, len); |
+ FillWithHoles(heap, elms, new_length, len); |
} |
} else if (item_count > actual_delete_count) { |
// Currently fixed arrays cannot grow too big, so |
@@ -843,7 +863,7 @@ |
int capacity = new_length + (new_length >> 1) + 16; |
Object* obj; |
{ MaybeObject* maybe_obj = |
- Heap::AllocateUninitializedFixedArray(capacity); |
+ heap->AllocateUninitializedFixedArray(capacity); |
if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
} |
FixedArray* new_elms = FixedArray::cast(obj); |
@@ -851,22 +871,22 @@ |
AssertNoAllocation no_gc; |
// Copy the part before actual_start as is. |
if (actual_start > 0) { |
- CopyElements(&no_gc, new_elms, 0, elms, 0, actual_start); |
+ CopyElements(heap, &no_gc, new_elms, 0, elms, 0, actual_start); |
} |
const int to_copy = len - actual_delete_count - actual_start; |
if (to_copy > 0) { |
- CopyElements(&no_gc, |
+ CopyElements(heap, &no_gc, |
new_elms, actual_start + item_count, |
elms, actual_start + actual_delete_count, |
to_copy); |
} |
- FillWithHoles(new_elms, new_length, capacity); |
+ FillWithHoles(heap, new_elms, new_length, capacity); |
elms = new_elms; |
array->set_elements(elms); |
} else { |
AssertNoAllocation no_gc; |
- MoveElements(&no_gc, |
+ MoveElements(heap, &no_gc, |
elms, actual_start + item_count, |
elms, actual_start + actual_delete_count, |
(len - actual_delete_count - actual_start)); |
@@ -887,11 +907,12 @@ |
BUILTIN(ArrayConcat) { |
- Context* global_context = Top::context()->global_context(); |
+ Heap* heap = isolate->heap(); |
+ Context* global_context = isolate->context()->global_context(); |
JSObject* array_proto = |
JSObject::cast(global_context->array_function()->prototype()); |
- if (!ArrayPrototypeHasNoElements(global_context, array_proto)) { |
- return CallJsBuiltin("ArrayConcat", args); |
+ if (!ArrayPrototypeHasNoElements(heap, global_context, array_proto)) { |
+ return CallJsBuiltin(isolate, "ArrayConcat", args); |
} |
// Iterate through all the arguments performing checks |
@@ -902,7 +923,7 @@ |
Object* arg = args[i]; |
if (!arg->IsJSArray() || !JSArray::cast(arg)->HasFastElements() |
|| JSArray::cast(arg)->GetPrototype() != array_proto) { |
- return CallJsBuiltin("ArrayConcat", args); |
+ return CallJsBuiltin(isolate, "ArrayConcat", args); |
} |
int len = Smi::cast(JSArray::cast(arg)->length())->value(); |
@@ -915,23 +936,23 @@ |
ASSERT(result_len >= 0); |
if (result_len > FixedArray::kMaxLength) { |
- return CallJsBuiltin("ArrayConcat", args); |
+ return CallJsBuiltin(isolate, "ArrayConcat", args); |
} |
} |
if (result_len == 0) { |
- return AllocateEmptyJSArray(); |
+ return AllocateEmptyJSArray(heap); |
} |
// Allocate result. |
Object* result; |
- { MaybeObject* maybe_result = AllocateJSArray(); |
+ { MaybeObject* maybe_result = AllocateJSArray(heap); |
if (!maybe_result->ToObject(&result)) return maybe_result; |
} |
JSArray* result_array = JSArray::cast(result); |
{ MaybeObject* maybe_result = |
- Heap::AllocateUninitializedFixedArray(result_len); |
+ heap->AllocateUninitializedFixedArray(result_len); |
if (!maybe_result->ToObject(&result)) return maybe_result; |
} |
FixedArray* result_elms = FixedArray::cast(result); |
@@ -944,7 +965,7 @@ |
int len = Smi::cast(array->length())->value(); |
if (len > 0) { |
FixedArray* elms = FixedArray::cast(array->elements()); |
- CopyElements(&no_gc, result_elms, start_pos, elms, 0, len); |
+ CopyElements(heap, &no_gc, result_elms, start_pos, elms, 0, len); |
start_pos += len; |
} |
} |
@@ -964,29 +985,29 @@ |
BUILTIN(StrictArgumentsCallee) { |
HandleScope scope; |
- return Top::Throw(*Factory::NewTypeError("strict_arguments_callee", |
- HandleVector<Object>(NULL, 0))); |
+ return isolate->Throw(*isolate->factory()->NewTypeError( |
+ "strict_arguments_callee", HandleVector<Object>(NULL, 0))); |
} |
BUILTIN(StrictArgumentsCaller) { |
HandleScope scope; |
- return Top::Throw(*Factory::NewTypeError("strict_arguments_caller", |
- HandleVector<Object>(NULL, 0))); |
+ return isolate->Throw(*isolate->factory()->NewTypeError( |
+ "strict_arguments_caller", HandleVector<Object>(NULL, 0))); |
} |
BUILTIN(StrictFunctionCaller) { |
HandleScope scope; |
- return Top::Throw(*Factory::NewTypeError("strict_function_caller", |
- HandleVector<Object>(NULL, 0))); |
+ return isolate->Throw(*isolate->factory()->NewTypeError( |
+ "strict_function_caller", HandleVector<Object>(NULL, 0))); |
} |
BUILTIN(StrictFunctionArguments) { |
HandleScope scope; |
- return Top::Throw(*Factory::NewTypeError("strict_function_arguments", |
- HandleVector<Object>(NULL, 0))); |
+ return isolate->Throw(*isolate->factory()->NewTypeError( |
+ "strict_function_arguments", HandleVector<Object>(NULL, 0))); |
} |
@@ -1000,7 +1021,8 @@ |
// overwritten with undefined. Arguments that do fit the expected |
// type is overwritten with the object in the prototype chain that |
// actually has that type. |
-static inline Object* TypeCheck(int argc, |
+static inline Object* TypeCheck(Heap* heap, |
+ int argc, |
Object** argv, |
FunctionTemplateInfo* info) { |
Object* recv = argv[0]; |
@@ -1012,12 +1034,12 @@ |
Object* holder = recv; |
if (!recv_type->IsUndefined()) { |
- for (; holder != Heap::null_value(); holder = holder->GetPrototype()) { |
+ for (; holder != heap->null_value(); holder = holder->GetPrototype()) { |
if (holder->IsInstanceOf(FunctionTemplateInfo::cast(recv_type))) { |
break; |
} |
} |
- if (holder == Heap::null_value()) return holder; |
+ if (holder == heap->null_value()) return holder; |
} |
Object* args_obj = sig->args(); |
// If there is no argument signature we're done |
@@ -1030,13 +1052,13 @@ |
if (argtype->IsUndefined()) continue; |
Object** arg = &argv[-1 - i]; |
Object* current = *arg; |
- for (; current != Heap::null_value(); current = current->GetPrototype()) { |
+ for (; current != heap->null_value(); current = current->GetPrototype()) { |
if (current->IsInstanceOf(FunctionTemplateInfo::cast(argtype))) { |
*arg = current; |
break; |
} |
} |
- if (current == Heap::null_value()) *arg = Heap::undefined_value(); |
+ if (current == heap->null_value()) *arg = heap->undefined_value(); |
} |
return holder; |
} |
@@ -1044,31 +1066,33 @@ |
template <bool is_construct> |
MUST_USE_RESULT static MaybeObject* HandleApiCallHelper( |
- BuiltinArguments<NEEDS_CALLED_FUNCTION> args) { |
- ASSERT(is_construct == CalledAsConstructor()); |
+ BuiltinArguments<NEEDS_CALLED_FUNCTION> args, Isolate* isolate) { |
+ ASSERT(is_construct == CalledAsConstructor(isolate)); |
+ Heap* heap = isolate->heap(); |
- HandleScope scope; |
+ HandleScope scope(isolate); |
Handle<JSFunction> function = args.called_function(); |
ASSERT(function->shared()->IsApiFunction()); |
FunctionTemplateInfo* fun_data = function->shared()->get_api_func_data(); |
if (is_construct) { |
- Handle<FunctionTemplateInfo> desc(fun_data); |
+ Handle<FunctionTemplateInfo> desc(fun_data, isolate); |
bool pending_exception = false; |
- Factory::ConfigureInstance(desc, Handle<JSObject>::cast(args.receiver()), |
- &pending_exception); |
- ASSERT(Top::has_pending_exception() == pending_exception); |
+ isolate->factory()->ConfigureInstance( |
+ desc, Handle<JSObject>::cast(args.receiver()), &pending_exception); |
+ ASSERT(isolate->has_pending_exception() == pending_exception); |
if (pending_exception) return Failure::Exception(); |
fun_data = *desc; |
} |
- Object* raw_holder = TypeCheck(args.length(), &args[0], fun_data); |
+ Object* raw_holder = TypeCheck(heap, args.length(), &args[0], fun_data); |
if (raw_holder->IsNull()) { |
// This function cannot be called with the given receiver. Abort! |
Handle<Object> obj = |
- Factory::NewTypeError("illegal_invocation", HandleVector(&function, 1)); |
- return Top::Throw(*obj); |
+ isolate->factory()->NewTypeError( |
+ "illegal_invocation", HandleVector(&function, 1)); |
+ return isolate->Throw(*obj); |
} |
Object* raw_call_data = fun_data->call_code(); |
@@ -1080,10 +1104,10 @@ |
Object* data_obj = call_data->data(); |
Object* result; |
- LOG(ApiObjectAccess("call", JSObject::cast(*args.receiver()))); |
+ LOG(isolate, ApiObjectAccess("call", JSObject::cast(*args.receiver()))); |
ASSERT(raw_holder->IsJSObject()); |
- CustomArguments custom; |
+ CustomArguments custom(isolate); |
v8::ImplementationUtilities::PrepareArgumentsData(custom.end(), |
data_obj, *function, raw_holder); |
@@ -1096,17 +1120,18 @@ |
v8::Handle<v8::Value> value; |
{ |
// Leaving JavaScript. |
- VMState state(EXTERNAL); |
- ExternalCallbackScope call_scope(v8::ToCData<Address>(callback_obj)); |
+ VMState state(isolate, EXTERNAL); |
+ ExternalCallbackScope call_scope(isolate, |
+ v8::ToCData<Address>(callback_obj)); |
value = callback(new_args); |
} |
if (value.IsEmpty()) { |
- result = Heap::undefined_value(); |
+ result = heap->undefined_value(); |
} else { |
result = *reinterpret_cast<Object**>(*value); |
} |
- RETURN_IF_SCHEDULED_EXCEPTION(); |
+ RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
if (!is_construct || result->IsJSObject()) return result; |
} |
@@ -1115,12 +1140,12 @@ |
BUILTIN(HandleApiCall) { |
- return HandleApiCallHelper<false>(args); |
+ return HandleApiCallHelper<false>(args, isolate); |
} |
BUILTIN(HandleApiCallConstruct) { |
- return HandleApiCallHelper<true>(args); |
+ return HandleApiCallHelper<true>(args, isolate); |
} |
@@ -1142,7 +1167,8 @@ |
BUILTIN(FastHandleApiCall) { |
- ASSERT(!CalledAsConstructor()); |
+ ASSERT(!CalledAsConstructor(isolate)); |
+ Heap* heap = isolate->heap(); |
const bool is_construct = false; |
// We expect four more arguments: callback, function, call data, and holder. |
@@ -1161,25 +1187,26 @@ |
VerifyTypeCheck(Utils::OpenHandle(*new_args.Holder()), |
Utils::OpenHandle(*new_args.Callee())); |
#endif |
- HandleScope scope; |
+ HandleScope scope(isolate); |
Object* result; |
v8::Handle<v8::Value> value; |
{ |
// Leaving JavaScript. |
- VMState state(EXTERNAL); |
- ExternalCallbackScope call_scope(v8::ToCData<Address>(callback_obj)); |
+ VMState state(isolate, EXTERNAL); |
+ ExternalCallbackScope call_scope(isolate, |
+ v8::ToCData<Address>(callback_obj)); |
v8::InvocationCallback callback = |
v8::ToCData<v8::InvocationCallback>(callback_obj); |
value = callback(new_args); |
} |
if (value.IsEmpty()) { |
- result = Heap::undefined_value(); |
+ result = heap->undefined_value(); |
} else { |
result = *reinterpret_cast<Object**>(*value); |
} |
- RETURN_IF_SCHEDULED_EXCEPTION(); |
+ RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
return result; |
} |
@@ -1188,11 +1215,13 @@ |
// API. The object can be called as either a constructor (using new) or just as |
// a function (without new). |
MUST_USE_RESULT static MaybeObject* HandleApiCallAsFunctionOrConstructor( |
+ Isolate* isolate, |
bool is_construct_call, |
BuiltinArguments<NO_EXTRA_ARGUMENTS> args) { |
// Non-functions are never called as constructors. Even if this is an object |
// called as a constructor the delegate call is not a construct call. |
- ASSERT(!CalledAsConstructor()); |
+ ASSERT(!CalledAsConstructor(isolate)); |
+ Heap* heap = isolate->heap(); |
Handle<Object> receiver = args.at<Object>(0); |
@@ -1215,11 +1244,10 @@ |
// Get the data for the call and perform the callback. |
Object* result; |
{ |
- HandleScope scope; |
+ HandleScope scope(isolate); |
+ LOG(isolate, ApiObjectAccess("call non-function", obj)); |
- LOG(ApiObjectAccess("call non-function", obj)); |
- |
- CustomArguments custom; |
+ CustomArguments custom(isolate); |
v8::ImplementationUtilities::PrepareArgumentsData(custom.end(), |
call_data->data(), constructor, obj); |
v8::Arguments new_args = v8::ImplementationUtilities::NewArguments( |
@@ -1230,18 +1258,19 @@ |
v8::Handle<v8::Value> value; |
{ |
// Leaving JavaScript. |
- VMState state(EXTERNAL); |
- ExternalCallbackScope call_scope(v8::ToCData<Address>(callback_obj)); |
+ VMState state(isolate, EXTERNAL); |
+ ExternalCallbackScope call_scope(isolate, |
+ v8::ToCData<Address>(callback_obj)); |
value = callback(new_args); |
} |
if (value.IsEmpty()) { |
- result = Heap::undefined_value(); |
+ result = heap->undefined_value(); |
} else { |
result = *reinterpret_cast<Object**>(*value); |
} |
} |
// Check for exceptions and return result. |
- RETURN_IF_SCHEDULED_EXCEPTION(); |
+ RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
return result; |
} |
@@ -1249,14 +1278,14 @@ |
// Handle calls to non-function objects created through the API. This delegate |
// function is used when the call is a normal function call. |
BUILTIN(HandleApiCallAsFunction) { |
- return HandleApiCallAsFunctionOrConstructor(false, args); |
+ return HandleApiCallAsFunctionOrConstructor(isolate, false, args); |
} |
// Handle calls to non-function objects created through the API. This delegate |
// function is used when the call is a construct call. |
BUILTIN(HandleApiCallAsConstructor) { |
- return HandleApiCallAsFunctionOrConstructor(true, args); |
+ return HandleApiCallAsFunctionOrConstructor(isolate, true, args); |
} |
@@ -1465,74 +1494,113 @@ |
} |
#endif |
-Object* Builtins::builtins_[builtin_count] = { NULL, }; |
-const char* Builtins::names_[builtin_count] = { NULL, }; |
+Builtins::Builtins() : initialized_(false) { |
+ memset(builtins_, 0, sizeof(builtins_[0]) * builtin_count); |
+ memset(names_, 0, sizeof(names_[0]) * builtin_count); |
+} |
+ |
+ |
+Builtins::~Builtins() { |
+} |
+ |
+ |
#define DEF_ENUM_C(name, ignore) FUNCTION_ADDR(Builtin_##name), |
- Address Builtins::c_functions_[cfunction_count] = { |
- BUILTIN_LIST_C(DEF_ENUM_C) |
- }; |
+Address const Builtins::c_functions_[cfunction_count] = { |
+ BUILTIN_LIST_C(DEF_ENUM_C) |
+}; |
#undef DEF_ENUM_C |
#define DEF_JS_NAME(name, ignore) #name, |
#define DEF_JS_ARGC(ignore, argc) argc, |
-const char* Builtins::javascript_names_[id_count] = { |
+const char* const Builtins::javascript_names_[id_count] = { |
BUILTINS_LIST_JS(DEF_JS_NAME) |
}; |
-int Builtins::javascript_argc_[id_count] = { |
+int const Builtins::javascript_argc_[id_count] = { |
BUILTINS_LIST_JS(DEF_JS_ARGC) |
}; |
#undef DEF_JS_NAME |
#undef DEF_JS_ARGC |
-static bool is_initialized = false; |
-void Builtins::Setup(bool create_heap_objects) { |
- ASSERT(!is_initialized); |
+struct BuiltinDesc { |
+ byte* generator; |
+ byte* c_code; |
+ const char* s_name; // name is only used for generating log information. |
+ int name; |
+ Code::Flags flags; |
+ BuiltinExtraArguments extra_args; |
+}; |
- // Create a scope for the handles in the builtins. |
- HandleScope scope; |
+class BuiltinFunctionTable { |
+ public: |
+ BuiltinFunctionTable() { |
+ Builtins::InitBuiltinFunctionTable(); |
+ } |
- struct BuiltinDesc { |
- byte* generator; |
- byte* c_code; |
- const char* s_name; // name is only used for generating log information. |
- int name; |
- Code::Flags flags; |
- BuiltinExtraArguments extra_args; |
- }; |
+ static const BuiltinDesc* functions() { return functions_; } |
-#define DEF_FUNCTION_PTR_C(name, extra_args) \ |
- { FUNCTION_ADDR(Generate_Adaptor), \ |
- FUNCTION_ADDR(Builtin_##name), \ |
- #name, \ |
- c_##name, \ |
- Code::ComputeFlags(Code::BUILTIN), \ |
- extra_args \ |
- }, |
+ private: |
+ static BuiltinDesc functions_[Builtins::builtin_count + 1]; |
-#define DEF_FUNCTION_PTR_A(name, kind, state, extra) \ |
- { FUNCTION_ADDR(Generate_##name), \ |
- NULL, \ |
- #name, \ |
- name, \ |
- Code::ComputeFlags(Code::kind, NOT_IN_LOOP, state, extra), \ |
- NO_EXTRA_ARGUMENTS \ |
- }, |
+ friend class Builtins; |
+}; |
- // Define array of pointers to generators and C builtin functions. |
- static BuiltinDesc functions[] = { |
- BUILTIN_LIST_C(DEF_FUNCTION_PTR_C) |
- BUILTIN_LIST_A(DEF_FUNCTION_PTR_A) |
- BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A) |
- // Terminator: |
- { NULL, NULL, NULL, builtin_count, static_cast<Code::Flags>(0), |
- NO_EXTRA_ARGUMENTS } |
- }; |
+BuiltinDesc BuiltinFunctionTable::functions_[Builtins::builtin_count + 1]; |
+static const BuiltinFunctionTable builtin_function_table_init; |
+ |
+// Define array of pointers to generators and C builtin functions. |
+// We do this in a sort of roundabout way so that we can do the initialization |
+// within the lexical scope of Builtins:: and within a context where |
+// Code::Flags names a non-abstract type. |
+void Builtins::InitBuiltinFunctionTable() { |
+ BuiltinDesc* functions = BuiltinFunctionTable::functions_; |
+ functions[builtin_count].generator = NULL; |
+ functions[builtin_count].c_code = NULL; |
+ functions[builtin_count].s_name = NULL; |
+ functions[builtin_count].name = builtin_count; |
+ functions[builtin_count].flags = static_cast<Code::Flags>(0); |
+ functions[builtin_count].extra_args = NO_EXTRA_ARGUMENTS; |
+ |
+#define DEF_FUNCTION_PTR_C(aname, aextra_args) \ |
+ functions->generator = FUNCTION_ADDR(Generate_Adaptor); \ |
+ functions->c_code = FUNCTION_ADDR(Builtin_##aname); \ |
+ functions->s_name = #aname; \ |
+ functions->name = c_##aname; \ |
+ functions->flags = Code::ComputeFlags(Code::BUILTIN); \ |
+ functions->extra_args = aextra_args; \ |
+ ++functions; |
+ |
+#define DEF_FUNCTION_PTR_A(aname, kind, state, extra) \ |
+ functions->generator = FUNCTION_ADDR(Generate_##aname); \ |
+ functions->c_code = NULL; \ |
+ functions->s_name = #aname; \ |
+ functions->name = aname; \ |
+ functions->flags = Code::ComputeFlags(Code::kind, \ |
+ NOT_IN_LOOP, \ |
+ state, \ |
+ extra); \ |
+ functions->extra_args = NO_EXTRA_ARGUMENTS; \ |
+ ++functions; |
+ |
+ BUILTIN_LIST_C(DEF_FUNCTION_PTR_C) |
+ BUILTIN_LIST_A(DEF_FUNCTION_PTR_A) |
+ BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A) |
+ |
#undef DEF_FUNCTION_PTR_C |
#undef DEF_FUNCTION_PTR_A |
+} |
+void Builtins::Setup(bool create_heap_objects) { |
+ ASSERT(!initialized_); |
+ Heap* heap = Isolate::Current()->heap(); |
+ |
+ // Create a scope for the handles in the builtins. |
+ HandleScope scope; |
+ |
+ 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]; |
@@ -1559,14 +1627,15 @@ |
// This simplifies things because we don't need to retry. |
AlwaysAllocateScope __scope__; |
{ MaybeObject* maybe_code = |
- Heap::CreateCode(desc, flags, masm.CodeObject()); |
+ heap->CreateCode(desc, flags, masm.CodeObject()); |
if (!maybe_code->ToObject(&code)) { |
v8::internal::V8::FatalProcessOutOfMemory("CreateCode"); |
} |
} |
} |
// Log the event and add the code to the builtins array. |
- PROFILE(CodeCreateEvent(Logger::BUILTIN_TAG, |
+ PROFILE(ISOLATE, |
+ CodeCreateEvent(Logger::BUILTIN_TAG, |
Code::cast(code), |
functions[i].s_name)); |
GDBJIT(AddCode(GDBJITInterface::BUILTIN, |
@@ -1588,12 +1657,12 @@ |
} |
// Mark as initialized. |
- is_initialized = true; |
+ initialized_ = true; |
} |
void Builtins::TearDown() { |
- is_initialized = false; |
+ initialized_ = false; |
} |
@@ -1603,7 +1672,8 @@ |
const char* Builtins::Lookup(byte* pc) { |
- if (is_initialized) { // may be called during initialization (disassembler!) |
+ // may be called during initialization (disassembler!) |
+ if (initialized_) { |
for (int i = 0; i < builtin_count; i++) { |
Code* entry = Code::cast(builtins_[i]); |
if (entry->contains(pc)) { |