vendor/v8/src/builtins.cc in mustang-0.0.1 vs vendor/v8/src/builtins.cc in mustang-0.1.0
- old
+ new
@@ -105,11 +105,10 @@
BUILTIN_LIST_C(DEF_ARG_TYPE)
#undef DEF_ARG_TYPE
} // namespace
-
// ----------------------------------------------------------------------------
// Support macro for defining builtins in C++.
// ----------------------------------------------------------------------------
//
// A builtin function is defined by writing:
@@ -121,41 +120,42 @@
// In the body of the builtin function the arguments can be accessed
// through the BuiltinArguments object args.
#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
// code below.
StackFrameIterator it;
ASSERT(it.frame()->is_exit());
it.Advance();
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;
Address caller_fp = Memory::Address_at(fp + kCallerOffset);
// This inlines the part of StackFrame::ComputeType that grabs the
@@ -170,34 +170,34 @@
return result;
}
// ----------------------------------------------------------------------------
-
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);
}
@@ -210,11 +210,11 @@
Object* obj = args[1];
if (obj->IsSmi()) {
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));
return array;
}
@@ -233,11 +233,11 @@
// Take the arguments as elements.
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;
}
AssertNoAllocation no_gc;
FixedArray* elms = FixedArray::cast(obj);
@@ -253,92 +253,96 @@
return array;
}
-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);
STATIC_ASSERT(FixedArray::kHeaderSize == 2 * kPointerSize);
Object** former_start = HeapObject::RawField(elms, 0);
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.
Object** zap = reinterpret_cast<Object**>(elms->address());
zap++; // Header of filler must be at least one word so skip that.
@@ -347,70 +351,74 @@
}
}
// 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(
elms->address() + to_trim * kPointerSize));
}
-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;
}
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);
int n_args = args.length() - 1;
for (int i = 0; i < n_args; i++) {
@@ -426,15 +434,18 @@
return *result;
}
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);
JSArray* array = JSArray::cast(receiver);
@@ -451,20 +462,20 @@
if (new_length > elms->length()) {
// 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);
}
@@ -480,22 +491,23 @@
return Smi::FromInt(new_length);
}
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);
// Set the length.
@@ -512,61 +524,65 @@
return top;
}
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.
array->set_length(Smi::FromInt(len - 1));
return first;
}
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);
ASSERT(array->HasFastElements());
@@ -579,26 +595,26 @@
if (new_length > elms->length()) {
// 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.
AssertNoAllocation no_gc;
WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
@@ -611,48 +627,49 @@
return Smi::FromInt(new_length);
}
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());
len = Smi::cast(array->length())->value();
} else {
// 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::arguments_length_index);
+ ->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);
}
}
}
ASSERT(len >= 0);
int n_arguments = args.length() - 1;
@@ -665,18 +682,18 @@
if (n_arguments > 0) {
Object* arg1 = args[1];
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);
}
}
}
// ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6.
@@ -688,27 +705,27 @@
: Min(relative_end, len);
// 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);
// Set the length.
@@ -716,19 +733,21 @@
return result_array;
}
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);
ASSERT(array->HasFastElements());
@@ -740,11 +759,11 @@
if (n_arguments > 0) {
Object* arg1 = args[1];
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)
: Min(relative_start, len);
@@ -762,40 +781,41 @@
if (n_arguments > 1) {
Object* arg2 = args[2];
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);
}
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);
// Set elements.
@@ -809,30 +829,30 @@
int new_length = len - actual_delete_count + item_count;
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) {
const int delta = actual_delete_count - item_count;
if (actual_start > 0) {
Object** start = elms->data_start();
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
// we should never hit this case.
ASSERT((item_count - actual_delete_count) <= (Smi::kMaxValue - len));
@@ -841,34 +861,34 @@
if (new_length > elms->length()) {
// New backing storage is needed.
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);
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));
}
}
@@ -885,26 +905,27 @@
return result_array;
}
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
// and calculating total length.
int n_arguments = args.length();
int result_len = 0;
for (int i = 0; i < n_arguments; i++) {
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();
// We shouldn't overflow when adding another len.
@@ -913,27 +934,27 @@
USE(kHalfOfMaxInt);
result_len += len;
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);
// Copy data.
@@ -942,11 +963,11 @@
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());
- CopyElements(&no_gc, result_elms, start_pos, elms, 0, len);
+ CopyElements(heap, &no_gc, result_elms, start_pos, elms, 0, len);
start_pos += len;
}
}
ASSERT(start_pos == result_len);
@@ -957,20 +978,53 @@
return result_array;
}
// -----------------------------------------------------------------------------
+// Strict mode poison pills
+
+
+BUILTIN(StrictArgumentsCallee) {
+ HandleScope scope;
+ return isolate->Throw(*isolate->factory()->NewTypeError(
+ "strict_arguments_callee", HandleVector<Object>(NULL, 0)));
+}
+
+
+BUILTIN(StrictArgumentsCaller) {
+ HandleScope scope;
+ return isolate->Throw(*isolate->factory()->NewTypeError(
+ "strict_arguments_caller", HandleVector<Object>(NULL, 0)));
+}
+
+
+BUILTIN(StrictFunctionCaller) {
+ HandleScope scope;
+ return isolate->Throw(*isolate->factory()->NewTypeError(
+ "strict_function_caller", HandleVector<Object>(NULL, 0)));
+}
+
+
+BUILTIN(StrictFunctionArguments) {
+ HandleScope scope;
+ return isolate->Throw(*isolate->factory()->NewTypeError(
+ "strict_function_arguments", HandleVector<Object>(NULL, 0)));
+}
+
+
+// -----------------------------------------------------------------------------
//
// Returns the holder JSObject if the function can legally be called
// with this receiver. Returns Heap::null_value() if the call is
// illegal. Any arguments that don't fit the expected type is
// 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];
Object* sig_obj = info->signature();
if (sig_obj->IsUndefined()) return recv;
@@ -978,16 +1032,16 @@
// If necessary, check the receiver
Object* recv_type = sig->receiver();
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
if (args_obj->IsUndefined()) return holder;
FixedArray* args = FixedArray::cast(args_obj);
@@ -996,49 +1050,51 @@
for (int i = 0; i < length; i++) {
Object* argtype = args->get(i);
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;
}
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();
if (!raw_call_data->IsUndefined()) {
CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
@@ -1046,14 +1102,14 @@
v8::InvocationCallback callback =
v8::ToCData<v8::InvocationCallback>(callback_obj);
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);
v8::Arguments new_args = v8::ImplementationUtilities::NewArguments(
custom.end(),
@@ -1062,35 +1118,36 @@
is_construct);
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;
}
return *args.receiver();
}
BUILTIN(HandleApiCall) {
- return HandleApiCallHelper<false>(args);
+ return HandleApiCallHelper<false>(args, isolate);
}
BUILTIN(HandleApiCallConstruct) {
- return HandleApiCallHelper<true>(args);
+ return HandleApiCallHelper<true>(args, isolate);
}
#ifdef DEBUG
@@ -1108,11 +1165,12 @@
#endif
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.
const int args_length = args.length() - 4;
ASSERT(args_length >= 0);
@@ -1127,42 +1185,45 @@
#ifdef DEBUG
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;
}
// Helper function to handle calls to non-function objects created through the
// 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);
// Get the object called.
JSObject* obj = JSObject::cast(*args.receiver());
@@ -1181,52 +1242,52 @@
v8::ToCData<v8::InvocationCallback>(callback_obj);
// 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(
custom.end(),
&args[0] - 1,
args.length() - 1,
is_construct_call);
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;
}
// 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);
}
static void Generate_LoadIC_ArrayLength(MacroAssembler* masm) {
LoadIC::GenerateArrayLength(masm);
@@ -1326,16 +1387,16 @@
StoreIC::GenerateNormal(masm);
}
static void Generate_StoreIC_Megamorphic(MacroAssembler* masm) {
- StoreIC::GenerateMegamorphic(masm, StoreIC::kStoreICNonStrict);
+ StoreIC::GenerateMegamorphic(masm, kNonStrictMode);
}
static void Generate_StoreIC_Megamorphic_Strict(MacroAssembler* masm) {
- StoreIC::GenerateMegamorphic(masm, StoreIC::kStoreICStrict);
+ StoreIC::GenerateMegamorphic(masm, kStrictMode);
}
static void Generate_StoreIC_ArrayLength(MacroAssembler* masm) {
StoreIC::GenerateArrayLength(masm);
@@ -1346,34 +1407,44 @@
StoreIC::GenerateArrayLength(masm);
}
static void Generate_StoreIC_GlobalProxy(MacroAssembler* masm) {
- StoreIC::GenerateGlobalProxy(masm);
+ StoreIC::GenerateGlobalProxy(masm, kNonStrictMode);
}
static void Generate_StoreIC_GlobalProxy_Strict(MacroAssembler* masm) {
- StoreIC::GenerateGlobalProxy(masm);
+ StoreIC::GenerateGlobalProxy(masm, kStrictMode);
}
static void Generate_KeyedStoreIC_Generic(MacroAssembler* masm) {
- KeyedStoreIC::GenerateGeneric(masm);
+ KeyedStoreIC::GenerateGeneric(masm, kNonStrictMode);
}
+static void Generate_KeyedStoreIC_Generic_Strict(MacroAssembler* masm) {
+ KeyedStoreIC::GenerateGeneric(masm, kStrictMode);
+}
+
+
static void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
KeyedStoreIC::GenerateMiss(masm);
}
static void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) {
KeyedStoreIC::GenerateInitialize(masm);
}
+static void Generate_KeyedStoreIC_Initialize_Strict(MacroAssembler* masm) {
+ KeyedStoreIC::GenerateInitialize(masm);
+}
+
+
#ifdef ENABLE_DEBUGGER_SUPPORT
static void Generate_LoadIC_DebugBreak(MacroAssembler* masm) {
Debug::GenerateLoadICDebugBreak(masm);
}
@@ -1421,87 +1492,127 @@
static void Generate_FrameDropper_LiveEdit(MacroAssembler* masm) {
Debug::GenerateFrameDropperLiveEdit(masm);
}
#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 = k##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_);
+ Isolate* isolate = Isolate::Current();
+ Heap* heap = isolate->heap();
+
+ // Create a scope for the handles in the builtins.
+ HandleScope scope(isolate);
+
+ 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];
// 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(buffer, sizeof buffer);
+ MacroAssembler masm(isolate, buffer, sizeof 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
@@ -1515,18 +1626,19 @@
{
// During startup it's OK to always allocate and defer GC to later.
// 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,
functions[i].s_name,
Code::cast(code)));
@@ -1544,33 +1656,53 @@
}
names_[i] = functions[i].s_name;
}
// Mark as initialized.
- is_initialized = true;
+ initialized_ = true;
}
void Builtins::TearDown() {
- is_initialized = false;
+ initialized_ = false;
}
void Builtins::IterateBuiltins(ObjectVisitor* v) {
v->VisitPointers(&builtins_[0], &builtins_[0] + builtin_count);
}
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)) {
return names_[i];
}
}
}
return NULL;
}
+
+
+#define DEFINE_BUILTIN_ACCESSOR_C(name, ignore) \
+Handle<Code> Builtins::name() { \
+ Code** code_address = \
+ reinterpret_cast<Code**>(builtin_address(k##name)); \
+ return Handle<Code>(code_address); \
+}
+#define DEFINE_BUILTIN_ACCESSOR_A(name, kind, state, extra) \
+Handle<Code> Builtins::name() { \
+ Code** code_address = \
+ reinterpret_cast<Code**>(builtin_address(k##name)); \
+ return Handle<Code>(code_address); \
+}
+BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
+BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
+BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
+#undef DEFINE_BUILTIN_ACCESSOR_C
+#undef DEFINE_BUILTIN_ACCESSOR_A
} } // namespace v8::internal