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

Unified Diff: src/builtins.cc

Issue 660095: Merge revision 3813 to 3930 from bleeding_edge to partial snapshots branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/partial_snapshots/
Patch Set: '' Created 10 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/builtins.h ('k') | src/checks.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/builtins.cc
===================================================================
--- src/builtins.cc (revision 3935)
+++ src/builtins.cc (working copy)
@@ -168,28 +168,6 @@
// ----------------------------------------------------------------------------
-Handle<Code> Builtins::GetCode(JavaScript id, bool* resolved) {
- Code* code = Builtins::builtin(Builtins::Illegal);
- *resolved = false;
-
- if (Top::context() != NULL) {
- Object* object = Top::builtins()->javascript_builtin(id);
- if (object->IsJSFunction()) {
- Handle<SharedFunctionInfo> shared(JSFunction::cast(object)->shared());
- // Make sure the number of parameters match the formal parameter count.
- ASSERT(shared->formal_parameter_count() ==
- Builtins::GetArgumentsCount(id));
- if (EnsureCompiled(shared, CLEAR_EXCEPTION)) {
- code = shared->code();
- *resolved = true;
- }
- }
- }
-
- return Handle<Code>(code);
-}
-
-
BUILTIN(Illegal) {
UNREACHABLE();
return Heap::undefined_value(); // Make compiler happy.
@@ -268,19 +246,19 @@
JSArray* array = JSArray::cast(*args.receiver());
ASSERT(array->HasFastElements());
- // Make sure we have space for the elements.
int len = Smi::cast(array->length())->value();
+ int to_add = args.length() - 1;
+ if (to_add == 0) {
+ return Smi::FromInt(len);
+ }
+ // Currently fixed arrays cannot grow too big, so
+ // we should never hit this case.
+ ASSERT(to_add <= (Smi::kMaxValue - len));
- // Set new length.
- int new_length = len + args.length() - 1;
+ int new_length = len + to_add;
FixedArray* elms = FixedArray::cast(array->elements());
- if (new_length <= elms->length()) {
- // Backing storage has extra space for the provided values.
- for (int index = 0; index < args.length() - 1; index++) {
- elms->set(index + len, args[index+1]);
- }
- } else {
+ if (new_length > elms->length()) {
// New backing storage is needed.
int capacity = new_length + (new_length >> 1) + 16;
Object* obj = Heap::AllocateFixedArrayWithHoles(capacity);
@@ -291,16 +269,21 @@
WriteBarrierMode mode = new_elms->GetWriteBarrierMode(no_gc);
// Fill out the new array with old elements.
for (int i = 0; i < len; i++) new_elms->set(i, elms->get(i), mode);
- // Add the provided values.
- for (int index = 0; index < args.length() - 1; index++) {
- new_elms->set(index + len, args[index+1], mode);
- }
- // Set the new backing storage.
- array->set_elements(new_elms);
+ elms = new_elms;
+ array->set_elements(elms);
}
+
+ AssertNoAllocation no_gc;
+ WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
+
+ // Add the provided values.
+ for (int index = 0; index < to_add; index++) {
+ elms->set(index + len, args[index + 1], mode);
+ }
+
// Set the length.
array->set_length(Smi::FromInt(new_length));
- return array->length();
+ return Smi::FromInt(new_length);
}
@@ -335,6 +318,355 @@
}
+static Object* GetElementToMove(uint32_t index,
+ FixedArray* elms,
+ JSObject* prototype) {
+ Object* e = elms->get(index);
+ if (e->IsTheHole() && prototype->HasElement(index)) {
+ e = prototype->GetElement(index);
+ }
+ return e;
+}
+
+
+BUILTIN(ArrayShift) {
+ JSArray* array = JSArray::cast(*args.receiver());
+ ASSERT(array->HasFastElements());
+
+ int len = Smi::cast(array->length())->value();
+ if (len == 0) return Heap::undefined_value();
+
+ // Fetch the prototype.
+ JSFunction* array_function =
+ Top::context()->global_context()->array_function();
+ JSObject* prototype = JSObject::cast(array_function->prototype());
+
+ FixedArray* elms = FixedArray::cast(array->elements());
+
+ // Get first element
+ Object* first = elms->get(0);
+ if (first->IsTheHole()) {
+ first = prototype->GetElement(0);
+ }
+
+ // Shift the elements.
+ for (int i = 0; i < len - 1; i++) {
+ elms->set(i, GetElementToMove(i + 1, elms, prototype));
+ }
+ elms->set(len - 1, Heap::the_hole_value());
+
+ // Set the length.
+ array->set_length(Smi::FromInt(len - 1));
+
+ return first;
+}
+
+
+BUILTIN(ArrayUnshift) {
+ JSArray* array = JSArray::cast(*args.receiver());
+ ASSERT(array->HasFastElements());
+
+ int len = Smi::cast(array->length())->value();
+ int to_add = args.length() - 1;
+ // Note that we cannot quit early if to_add == 0 as
+ // values should be lifted from prototype into
+ // the array.
+
+ int new_length = len + to_add;
+ // Currently fixed arrays cannot grow too big, so
+ // we should never hit this case.
+ ASSERT(to_add <= (Smi::kMaxValue - len));
+
+ FixedArray* elms = FixedArray::cast(array->elements());
+
+ // Fetch the prototype.
+ JSFunction* array_function =
+ Top::context()->global_context()->array_function();
+ JSObject* prototype = JSObject::cast(array_function->prototype());
+
+ if (new_length > elms->length()) {
+ // New backing storage is needed.
+ int capacity = new_length + (new_length >> 1) + 16;
+ Object* obj = Heap::AllocateFixedArrayWithHoles(capacity);
+ if (obj->IsFailure()) return obj;
+
+ AssertNoAllocation no_gc;
+ FixedArray* new_elms = FixedArray::cast(obj);
+ WriteBarrierMode mode = new_elms->GetWriteBarrierMode(no_gc);
+ // Fill out the new array with old elements.
+ for (int i = 0; i < len; i++)
+ new_elms->set(to_add + i,
+ GetElementToMove(i, elms, prototype),
+ mode);
+
+ elms = new_elms;
+ array->set_elements(elms);
+ } else {
+ AssertNoAllocation no_gc;
+ WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
+
+ // Move elements to the right
+ for (int i = 0; i < len; i++) {
+ elms->set(new_length - i - 1,
+ GetElementToMove(len - i - 1, elms, prototype),
+ mode);
+ }
+ }
+
+ // Add the provided values.
+ AssertNoAllocation no_gc;
+ WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
+ for (int i = 0; i < to_add; i++) {
+ elms->set(i, args[i + 1], mode);
+ }
+
+ // Set the length.
+ array->set_length(Smi::FromInt(new_length));
+ return Smi::FromInt(new_length);
+}
+
+
+static Object* CallJsBuiltin(const char* name,
+ BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
+ HandleScope handleScope;
+
+ Handle<Object> js_builtin =
+ GetProperty(Handle<JSObject>(Top::global_context()->builtins()),
+ name);
+ ASSERT(js_builtin->IsJSFunction());
+ Handle<JSFunction> function(Handle<JSFunction>::cast(js_builtin));
+ Vector<Object**> argv(Vector<Object**>::New(args.length() - 1));
+ int n_args = args.length() - 1;
+ for (int i = 0; i < n_args; i++) {
+ argv[i] = &args[i + 1];
+ }
+ bool pending_exception = false;
+ Handle<Object> result = Execution::Call(function,
+ args.receiver(),
+ n_args,
+ argv.start(),
+ &pending_exception);
+ if (pending_exception) return Failure::Exception();
+ return *result;
+}
+
+
+BUILTIN(ArraySlice) {
+ JSArray* array = JSArray::cast(*args.receiver());
+ ASSERT(array->HasFastElements());
+
+ int len = Smi::cast(array->length())->value();
+
+ int n_arguments = args.length() - 1;
+
+ // Note carefully choosen defaults---if argument is missing,
+ // it's undefined which gets converted to 0 for relativeStart
+ // and to len for relativeEnd.
+ int relativeStart = 0;
+ int relativeEnd = len;
+ if (n_arguments > 0) {
+ Object* arg1 = args[1];
+ if (arg1->IsSmi()) {
+ relativeStart = Smi::cast(arg1)->value();
+ } else if (!arg1->IsUndefined()) {
+ return CallJsBuiltin("ArraySlice", args);
+ }
+ if (n_arguments > 1) {
+ Object* arg2 = args[2];
+ if (arg2->IsSmi()) {
+ relativeEnd = Smi::cast(arg2)->value();
+ } else if (!arg2->IsUndefined()) {
+ return CallJsBuiltin("ArraySlice", args);
+ }
+ }
+ }
+
+ // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6.
+ int k = (relativeStart < 0) ? Max(len + relativeStart, 0)
+ : Min(relativeStart, len);
+
+ // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8.
+ int final = (relativeEnd < 0) ? Max(len + relativeEnd, 0)
+ : Min(relativeEnd, len);
+
+ // Calculate the length of result array.
+ int result_len = final - k;
+ if (result_len < 0) {
+ result_len = 0;
+ }
+
+ JSFunction* array_function =
+ Top::context()->global_context()->array_function();
+ Object* result = Heap::AllocateJSObject(array_function);
+ if (result->IsFailure()) return result;
+ JSArray* result_array = JSArray::cast(result);
+
+ result = Heap::AllocateFixedArrayWithHoles(result_len);
+ if (result->IsFailure()) return result;
+ FixedArray* result_elms = FixedArray::cast(result);
+
+ FixedArray* elms = FixedArray::cast(array->elements());
+
+ // Fetch the prototype.
+ JSObject* prototype = JSObject::cast(array_function->prototype());
+
+ AssertNoAllocation no_gc;
+ WriteBarrierMode mode = result_elms->GetWriteBarrierMode(no_gc);
+
+ // Fill newly created array.
+ for (int i = 0; i < result_len; i++) {
+ result_elms->set(i,
+ GetElementToMove(k + i, elms, prototype),
+ mode);
+ }
+
+ // Set elements.
+ result_array->set_elements(result_elms);
+
+ // Set the length.
+ result_array->set_length(Smi::FromInt(result_len));
+ return result_array;
+}
+
+
+BUILTIN(ArraySplice) {
+ JSArray* array = JSArray::cast(*args.receiver());
+ ASSERT(array->HasFastElements());
+
+ int len = Smi::cast(array->length())->value();
+
+ int n_arguments = args.length() - 1;
+
+ // SpiderMonkey and JSC return undefined in the case where no
+ // arguments are given instead of using the implicit undefined
+ // arguments. This does not follow ECMA-262, but we do the same for
+ // compatibility.
+ // TraceMonkey follows ECMA-262 though.
+ if (n_arguments == 0) {
+ return Heap::undefined_value();
+ }
+
+ int relativeStart = 0;
+ Object* arg1 = args[1];
+ if (arg1->IsSmi()) {
+ relativeStart = Smi::cast(arg1)->value();
+ } else if (!arg1->IsUndefined()) {
+ return CallJsBuiltin("ArraySplice", args);
+ }
+ int actualStart = (relativeStart < 0) ? Max(len + relativeStart, 0)
+ : Min(relativeStart, len);
+
+ // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
+ // given differently from when an undefined delete count is given.
+ // This does not follow ECMA-262, but we do the same for
+ // compatibility.
+ int deleteCount = len;
+ if (n_arguments > 1) {
+ Object* arg2 = args[2];
+ if (arg2->IsSmi()) {
+ deleteCount = Smi::cast(arg2)->value();
+ } else {
+ return CallJsBuiltin("ArraySplice", args);
+ }
+ }
+ int actualDeleteCount = Min(Max(deleteCount, 0), len - actualStart);
+
+ JSFunction* array_function =
+ Top::context()->global_context()->array_function();
+
+ // Allocate result array.
+ Object* result = Heap::AllocateJSObject(array_function);
+ if (result->IsFailure()) return result;
+ JSArray* result_array = JSArray::cast(result);
+
+ result = Heap::AllocateFixedArrayWithHoles(actualDeleteCount);
+ if (result->IsFailure()) return result;
+ FixedArray* result_elms = FixedArray::cast(result);
+
+ FixedArray* elms = FixedArray::cast(array->elements());
+
+ // Fetch the prototype.
+ JSObject* prototype = JSObject::cast(array_function->prototype());
+
+ AssertNoAllocation no_gc;
+ WriteBarrierMode mode = result_elms->GetWriteBarrierMode(no_gc);
+
+ // Fill newly created array.
+ for (int k = 0; k < actualDeleteCount; k++) {
+ result_elms->set(k,
+ GetElementToMove(actualStart + k, elms, prototype),
+ mode);
+ }
+
+ // Set elements.
+ result_array->set_elements(result_elms);
+
+ // Set the length.
+ result_array->set_length(Smi::FromInt(actualDeleteCount));
+
+ int itemCount = (n_arguments > 1) ? (n_arguments - 2) : 0;
+
+ int new_length = len - actualDeleteCount + itemCount;
+
+ mode = elms->GetWriteBarrierMode(no_gc);
+ if (itemCount < actualDeleteCount) {
+ // Shrink the array.
+ for (int k = actualStart; k < (len - actualDeleteCount); k++) {
+ elms->set(k + itemCount,
+ GetElementToMove(k + actualDeleteCount, elms, prototype),
+ mode);
+ }
+
+ for (int k = len; k > new_length; k--) {
+ elms->set(k - 1, Heap::the_hole_value());
+ }
+ } else if (itemCount > actualDeleteCount) {
+ // Currently fixed arrays cannot grow too big, so
+ // we should never hit this case.
+ ASSERT((itemCount - actualDeleteCount) <= (Smi::kMaxValue - len));
+
+ FixedArray* source_elms = elms;
+
+ // Check if array need to grow.
+ if (new_length > elms->length()) {
+ // New backing storage is needed.
+ int capacity = new_length + (new_length >> 1) + 16;
+ Object* obj = Heap::AllocateFixedArrayWithHoles(capacity);
+ if (obj->IsFailure()) return obj;
+
+ FixedArray* new_elms = FixedArray::cast(obj);
+ mode = new_elms->GetWriteBarrierMode(no_gc);
+
+ // Copy the part before actualStart as is.
+ for (int k = 0; k < actualStart; k++) {
+ new_elms->set(k, elms->get(k), mode);
+ }
+
+ source_elms = elms;
+ elms = new_elms;
+ array->set_elements(elms);
+ }
+
+ for (int k = len - actualDeleteCount; k > actualStart; k--) {
+ elms->set(k + itemCount - 1,
+ GetElementToMove(k + actualDeleteCount - 1,
+ source_elms,
+ prototype),
+ mode);
+ }
+ }
+
+ for (int k = actualStart; k < actualStart + itemCount; k++) {
+ elms->set(k, args[3 + k - actualStart], mode);
+ }
+
+ // Set the length.
+ array->set_length(Smi::FromInt(new_length));
+
+ return result_array;
+}
+
+
// -----------------------------------------------------------------------------
//
@@ -474,6 +806,76 @@
}
+#ifdef DEBUG
+
+static void VerifyTypeCheck(Handle<JSObject> object,
+ Handle<JSFunction> function) {
+ FunctionTemplateInfo* info =
+ FunctionTemplateInfo::cast(function->shared()->function_data());
+ if (info->signature()->IsUndefined()) return;
+ SignatureInfo* signature = SignatureInfo::cast(info->signature());
+ Object* receiver_type = signature->receiver();
+ if (receiver_type->IsUndefined()) return;
+ FunctionTemplateInfo* type = FunctionTemplateInfo::cast(receiver_type);
+ ASSERT(object->IsInstanceOf(type));
+}
+
+#endif
+
+
+BUILTIN(FastHandleApiCall) {
+ ASSERT(!CalledAsConstructor());
+ const bool is_construct = false;
+
+ // We expect four more arguments: function, callback, call data, and holder.
+ const int args_length = args.length() - 4;
+ ASSERT(args_length >= 0);
+
+ Handle<JSFunction> function = args.at<JSFunction>(args_length);
+ Object* callback_obj = args[args_length + 1];
+ Handle<Object> data_handle = args.at<Object>(args_length + 2);
+ Handle<JSObject> checked_holder = args.at<JSObject>(args_length + 3);
+
+#ifdef DEBUG
+ VerifyTypeCheck(checked_holder, function);
+#endif
+
+ v8::Local<v8::Object> holder = v8::Utils::ToLocal(checked_holder);
+ v8::Local<v8::Function> callee = v8::Utils::ToLocal(function);
+ v8::InvocationCallback callback =
+ v8::ToCData<v8::InvocationCallback>(callback_obj);
+ v8::Local<v8::Value> data = v8::Utils::ToLocal(data_handle);
+
+ v8::Arguments new_args = v8::ImplementationUtilities::NewArguments(
+ data,
+ holder,
+ callee,
+ is_construct,
+ reinterpret_cast<void**>(&args[0] - 1),
+ args_length - 1);
+
+ HandleScope scope;
+ Object* result;
+ v8::Handle<v8::Value> value;
+ {
+ // Leaving JavaScript.
+ VMState state(EXTERNAL);
+#ifdef ENABLE_LOGGING_AND_PROFILING
+ state.set_external_callback(v8::ToCData<Address>(callback_obj));
+#endif
+ value = callback(new_args);
+ }
+ if (value.IsEmpty()) {
+ result = Heap::undefined_value();
+ } else {
+ result = *reinterpret_cast<Object**>(*value);
+ }
+
+ RETURN_IF_SCHEDULED_EXCEPTION();
+ 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).
@@ -657,7 +1059,11 @@
KeyedLoadIC::GeneratePreMonomorphic(masm);
}
+static void Generate_KeyedLoadIC_IndexedInterceptor(MacroAssembler* masm) {
+ KeyedLoadIC::GenerateIndexedInterceptor(masm);
+}
+
static void Generate_StoreIC_Initialize(MacroAssembler* masm) {
StoreIC::GenerateInitialize(masm);
}
@@ -668,15 +1074,16 @@
}
-static void Generate_StoreIC_ExtendStorage(MacroAssembler* masm) {
- StoreIC::GenerateExtendStorage(masm);
-}
-
static void Generate_StoreIC_Megamorphic(MacroAssembler* masm) {
StoreIC::GenerateMegamorphic(masm);
}
+static void Generate_StoreIC_ArrayLength(MacroAssembler* masm) {
+ StoreIC::GenerateArrayLength(masm);
+}
+
+
static void Generate_KeyedStoreIC_Generic(MacroAssembler* masm) {
KeyedStoreIC::GenerateGeneric(masm);
}
@@ -720,11 +1127,6 @@
}
-static void Generate_KeyedStoreIC_ExtendStorage(MacroAssembler* masm) {
- KeyedStoreIC::GenerateExtendStorage(masm);
-}
-
-
static void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
KeyedStoreIC::GenerateMiss(masm);
}
@@ -869,9 +1271,6 @@
v8::internal::V8::FatalProcessOutOfMemory("CreateCode");
}
}
- // Add any unresolved jumps or calls to the fixup list in the
- // bootstrapper.
- Bootstrapper::AddFixup(Code::cast(code), &masm);
// Log the event and add the code to the builtins array.
LOG(CodeCreateEvent(Logger::BUILTIN_TAG,
Code::cast(code), functions[i].s_name));
« no previous file with comments | « src/builtins.h ('k') | src/checks.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698