Version 3.23.12
Performance and stability improvements on all platforms.
git-svn-id: http://v8.googlecode.com/svn/trunk@18076 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/allocation-site-scopes.cc b/src/allocation-site-scopes.cc
index 8097045..31120b9 100644
--- a/src/allocation-site-scopes.cc
+++ b/src/allocation-site-scopes.cc
@@ -82,27 +82,4 @@
}
}
-
-Handle<AllocationSite> AllocationSiteUsageContext::EnterNewScope() {
- if (top().is_null()) {
- InitializeTraversal(top_site_);
- } else {
- // Advance current site
- Object* nested_site = current()->nested_site();
- // Something is wrong if we advance to the end of the list here.
- ASSERT(nested_site->IsAllocationSite());
- update_current_site(AllocationSite::cast(nested_site));
- }
- return Handle<AllocationSite>(*current(), isolate());
-}
-
-
-void AllocationSiteUsageContext::ExitScope(
- Handle<AllocationSite> scope_site,
- Handle<JSObject> object) {
- // This assert ensures that we are pointing at the right sub-object in a
- // recursive walk of a nested literal.
- ASSERT(object.is_null() || *object == scope_site->transition_info());
-}
-
} } // namespace v8::internal
diff --git a/src/allocation-site-scopes.h b/src/allocation-site-scopes.h
index 1c3afdf..f106c5e 100644
--- a/src/allocation-site-scopes.h
+++ b/src/allocation-site-scopes.h
@@ -45,7 +45,6 @@
isolate_ = isolate;
activated_ = activated;
};
- virtual ~AllocationSiteContext() {}
Handle<AllocationSite> top() { return top_; }
Handle<AllocationSite> current() { return current_; }
@@ -53,19 +52,13 @@
// If activated, then recursively create mementos
bool activated() const { return activated_; }
- // Returns the AllocationSite that matches this scope.
- virtual Handle<AllocationSite> EnterNewScope() = 0;
-
- // scope_site should be the handle returned by the matching EnterNewScope()
- virtual void ExitScope(Handle<AllocationSite> scope_site,
- Handle<JSObject> object) = 0;
+ Isolate* isolate() { return isolate_; }
protected:
void update_current_site(AllocationSite* site) {
*(current_.location()) = site;
}
- Isolate* isolate() { return isolate_; }
void InitializeTraversal(Handle<AllocationSite> site) {
top_ = site;
current_ = Handle<AllocationSite>(*top_, isolate());
@@ -86,9 +79,8 @@
explicit AllocationSiteCreationContext(Isolate* isolate)
: AllocationSiteContext(isolate, true) { }
- virtual Handle<AllocationSite> EnterNewScope() V8_OVERRIDE;
- virtual void ExitScope(Handle<AllocationSite> site,
- Handle<JSObject> object) V8_OVERRIDE;
+ Handle<AllocationSite> EnterNewScope();
+ void ExitScope(Handle<AllocationSite> site, Handle<JSObject> object);
};
@@ -101,9 +93,25 @@
: AllocationSiteContext(isolate, activated),
top_site_(site) { }
- virtual Handle<AllocationSite> EnterNewScope() V8_OVERRIDE;
- virtual void ExitScope(Handle<AllocationSite> site,
- Handle<JSObject> object) V8_OVERRIDE;
+ inline Handle<AllocationSite> EnterNewScope() {
+ if (top().is_null()) {
+ InitializeTraversal(top_site_);
+ } else {
+ // Advance current site
+ Object* nested_site = current()->nested_site();
+ // Something is wrong if we advance to the end of the list here.
+ ASSERT(nested_site->IsAllocationSite());
+ update_current_site(AllocationSite::cast(nested_site));
+ }
+ return Handle<AllocationSite>(*current(), isolate());
+ }
+
+ inline void ExitScope(Handle<AllocationSite> scope_site,
+ Handle<JSObject> object) {
+ // This assert ensures that we are pointing at the right sub-object in a
+ // recursive walk of a nested literal.
+ ASSERT(object.is_null() || *object == scope_site->transition_info());
+ }
private:
Handle<AllocationSite> top_site_;
diff --git a/src/api.cc b/src/api.cc
index 18aca94..30a7ef8 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -1078,32 +1078,42 @@
}
Local<FunctionTemplate> FunctionTemplate::New(
+ Isolate* isolate,
FunctionCallback callback,
v8::Handle<Value> data,
v8::Handle<Signature> signature,
int length) {
- i::Isolate* isolate = i::Isolate::Current();
- EnsureInitializedForIsolate(isolate, "v8::FunctionTemplate::New()");
- LOG_API(isolate, "FunctionTemplate::New");
- ENTER_V8(isolate);
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ EnsureInitializedForIsolate(i_isolate, "v8::FunctionTemplate::New()");
+ LOG_API(i_isolate, "FunctionTemplate::New");
+ ENTER_V8(i_isolate);
return FunctionTemplateNew(
- isolate, callback, data, signature, length, false);
+ i_isolate, callback, data, signature, length, false);
}
-Local<Signature> Signature::New(Handle<FunctionTemplate> receiver,
- int argc, Handle<FunctionTemplate> argv[]) {
- i::Isolate* isolate = i::Isolate::Current();
- EnsureInitializedForIsolate(isolate, "v8::Signature::New()");
- LOG_API(isolate, "Signature::New");
- ENTER_V8(isolate);
+Local<FunctionTemplate> FunctionTemplate::New(
+ FunctionCallback callback,
+ v8::Handle<Value> data,
+ v8::Handle<Signature> signature,
+ int length) {
+ return New(Isolate::GetCurrent(), callback, data, signature, length);
+}
+
+Local<Signature> Signature::New(Isolate* isolate,
+ Handle<FunctionTemplate> receiver, int argc,
+ Handle<FunctionTemplate> argv[]) {
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ EnsureInitializedForIsolate(i_isolate, "v8::Signature::New()");
+ LOG_API(i_isolate, "Signature::New");
+ ENTER_V8(i_isolate);
i::Handle<i::Struct> struct_obj =
- isolate->factory()->NewStruct(i::SIGNATURE_INFO_TYPE);
+ i_isolate->factory()->NewStruct(i::SIGNATURE_INFO_TYPE);
i::Handle<i::SignatureInfo> obj =
i::Handle<i::SignatureInfo>::cast(struct_obj);
if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver));
if (argc > 0) {
- i::Handle<i::FixedArray> args = isolate->factory()->NewFixedArray(argc);
+ i::Handle<i::FixedArray> args = i_isolate->factory()->NewFixedArray(argc);
for (int i = 0; i < argc; i++) {
if (!argv[i].IsEmpty())
args->set(i, *Utils::OpenHandle(*argv[i]));
@@ -1114,6 +1124,20 @@
}
+Local<Signature> Signature::New(Handle<FunctionTemplate> receiver,
+ int argc, Handle<FunctionTemplate> argv[]) {
+ return New(Isolate::GetCurrent(), receiver, argc, argv);
+}
+
+
+Local<AccessorSignature> AccessorSignature::New(
+ Isolate* isolate,
+ Handle<FunctionTemplate> receiver) {
+ return Utils::AccessorSignatureToLocal(Utils::OpenHandle(*receiver));
+}
+
+
+// While this is just a cast, it's lame not to use an Isolate parameter.
Local<AccessorSignature> AccessorSignature::New(
Handle<FunctionTemplate> receiver) {
return Utils::AccessorSignatureToLocal(Utils::OpenHandle(*receiver));
@@ -1363,7 +1387,7 @@
i::Handle<i::FunctionTemplateInfo> handle = Utils::OpenHandle(this);
if (handle->instance_template()->IsUndefined()) {
Local<ObjectTemplate> templ =
- ObjectTemplate::New(ToApiHandle<FunctionTemplate>(handle));
+ ObjectTemplate::New(isolate, ToApiHandle<FunctionTemplate>(handle));
handle->set_instance_template(*Utils::OpenHandle(*templ));
}
i::Handle<i::ObjectTemplateInfo> result(
@@ -1410,14 +1434,19 @@
// --- O b j e c t T e m p l a t e ---
+Local<ObjectTemplate> ObjectTemplate::New(Isolate* isolate) {
+ return New(reinterpret_cast<i::Isolate*>(isolate), Local<FunctionTemplate>());
+}
+
+
Local<ObjectTemplate> ObjectTemplate::New() {
- return New(Local<FunctionTemplate>());
+ return New(i::Isolate::Current(), Local<FunctionTemplate>());
}
Local<ObjectTemplate> ObjectTemplate::New(
+ i::Isolate* isolate,
v8::Handle<FunctionTemplate> constructor) {
- i::Isolate* isolate = i::Isolate::Current();
EnsureInitializedForIsolate(isolate, "v8::ObjectTemplate::New()");
LOG_API(isolate, "ObjectTemplate::New");
ENTER_V8(isolate);
@@ -2285,10 +2314,15 @@
}
+void Message::PrintCurrentStackTrace(Isolate* isolate, FILE* out) {
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ ENTER_V8(i_isolate);
+ i_isolate->PrintCurrentStackTrace(out);
+}
+
+
void Message::PrintCurrentStackTrace(FILE* out) {
- i::Isolate* isolate = i::Isolate::Current();
- ENTER_V8(isolate);
- isolate->PrintCurrentStackTrace(out);
+ PrintCurrentStackTrace(Isolate::GetCurrent(), out);
}
@@ -2319,13 +2353,21 @@
}
+Local<StackTrace> StackTrace::CurrentStackTrace(
+ Isolate* isolate,
+ int frame_limit,
+ StackTraceOptions options) {
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ ENTER_V8(i_isolate);
+ i::Handle<i::JSArray> stackTrace =
+ i_isolate->CaptureCurrentStackTrace(frame_limit, options);
+ return Utils::StackTraceToLocal(stackTrace);
+}
+
+
Local<StackTrace> StackTrace::CurrentStackTrace(int frame_limit,
StackTraceOptions options) {
- i::Isolate* isolate = i::Isolate::Current();
- ENTER_V8(isolate);
- i::Handle<i::JSArray> stackTrace =
- isolate->CaptureCurrentStackTrace(frame_limit, options);
- return Utils::StackTraceToLocal(stackTrace);
+ return CurrentStackTrace(Isolate::GetCurrent(), frame_limit, options);
}
@@ -5646,18 +5688,25 @@
Local<String> v8::String::NewExternal(
+ Isolate* isolate,
v8::String::ExternalStringResource* resource) {
- i::Isolate* isolate = i::Isolate::Current();
- EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()");
- LOG_API(isolate, "String::NewExternal");
- ENTER_V8(isolate);
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ EnsureInitializedForIsolate(i_isolate, "v8::String::NewExternal()");
+ LOG_API(i_isolate, "String::NewExternal");
+ ENTER_V8(i_isolate);
CHECK(resource && resource->data());
- i::Handle<i::String> result = NewExternalStringHandle(isolate, resource);
- isolate->heap()->external_string_table()->AddString(*result);
+ i::Handle<i::String> result = NewExternalStringHandle(i_isolate, resource);
+ i_isolate->heap()->external_string_table()->AddString(*result);
return Utils::ToLocal(result);
}
+Local<String> v8::String::NewExternal(
+ v8::String::ExternalStringResource* resource) {
+ return NewExternal(Isolate::GetCurrent(), resource);
+}
+
+
bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
i::Handle<i::String> obj = Utils::OpenHandle(this);
i::Isolate* isolate = obj->GetIsolate();
@@ -5695,18 +5744,26 @@
Local<String> v8::String::NewExternal(
+ Isolate* isolate,
v8::String::ExternalAsciiStringResource* resource) {
- i::Isolate* isolate = i::Isolate::Current();
- EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()");
- LOG_API(isolate, "String::NewExternal");
- ENTER_V8(isolate);
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ EnsureInitializedForIsolate(i_isolate, "v8::String::NewExternal()");
+ LOG_API(i_isolate, "String::NewExternal");
+ ENTER_V8(i_isolate);
CHECK(resource && resource->data());
- i::Handle<i::String> result = NewExternalAsciiStringHandle(isolate, resource);
- isolate->heap()->external_string_table()->AddString(*result);
+ i::Handle<i::String> result =
+ NewExternalAsciiStringHandle(i_isolate, resource);
+ i_isolate->heap()->external_string_table()->AddString(*result);
return Utils::ToLocal(result);
}
+Local<String> v8::String::NewExternal(
+ v8::String::ExternalAsciiStringResource* resource) {
+ return NewExternal(Isolate::GetCurrent(), resource);
+}
+
+
bool v8::String::MakeExternal(
v8::String::ExternalAsciiStringResource* resource) {
i::Handle<i::String> obj = Utils::OpenHandle(this);
@@ -5762,25 +5819,35 @@
}
-Local<v8::Object> v8::Object::New() {
- i::Isolate* isolate = i::Isolate::Current();
- EnsureInitializedForIsolate(isolate, "v8::Object::New()");
- LOG_API(isolate, "Object::New");
- ENTER_V8(isolate);
+Local<v8::Object> v8::Object::New(Isolate* isolate) {
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ EnsureInitializedForIsolate(i_isolate, "v8::Object::New()");
+ LOG_API(i_isolate, "Object::New");
+ ENTER_V8(i_isolate);
i::Handle<i::JSObject> obj =
- isolate->factory()->NewJSObject(isolate->object_function());
+ i_isolate->factory()->NewJSObject(i_isolate->object_function());
+ return Utils::ToLocal(obj);
+}
+
+
+Local<v8::Object> v8::Object::New() {
+ return New(Isolate::GetCurrent());
+}
+
+
+Local<v8::Value> v8::NumberObject::New(Isolate* isolate, double value) {
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ EnsureInitializedForIsolate(i_isolate, "v8::NumberObject::New()");
+ LOG_API(i_isolate, "NumberObject::New");
+ ENTER_V8(i_isolate);
+ i::Handle<i::Object> number = i_isolate->factory()->NewNumber(value);
+ i::Handle<i::Object> obj = i_isolate->factory()->ToObject(number);
return Utils::ToLocal(obj);
}
Local<v8::Value> v8::NumberObject::New(double value) {
- i::Isolate* isolate = i::Isolate::Current();
- EnsureInitializedForIsolate(isolate, "v8::NumberObject::New()");
- LOG_API(isolate, "NumberObject::New");
- ENTER_V8(isolate);
- i::Handle<i::Object> number = isolate->factory()->NewNumber(value);
- i::Handle<i::Object> obj = isolate->factory()->ToObject(number);
- return Utils::ToLocal(obj);
+ return New(Isolate::GetCurrent(), value);
}
@@ -5858,23 +5925,28 @@
}
-Local<v8::Value> v8::Date::New(double time) {
- i::Isolate* isolate = i::Isolate::Current();
- EnsureInitializedForIsolate(isolate, "v8::Date::New()");
- LOG_API(isolate, "Date::New");
+Local<v8::Value> v8::Date::New(Isolate* isolate, double time) {
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ EnsureInitializedForIsolate(i_isolate, "v8::Date::New()");
+ LOG_API(i_isolate, "Date::New");
if (std::isnan(time)) {
// Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
time = i::OS::nan_value();
}
- ENTER_V8(isolate);
- EXCEPTION_PREAMBLE(isolate);
+ ENTER_V8(i_isolate);
+ EXCEPTION_PREAMBLE(i_isolate);
i::Handle<i::Object> obj =
- i::Execution::NewDate(isolate, time, &has_pending_exception);
- EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Value>());
+ i::Execution::NewDate(i_isolate, time, &has_pending_exception);
+ EXCEPTION_BAILOUT_CHECK(i_isolate, Local<v8::Value>());
return Utils::ToLocal(obj);
}
+Local<v8::Value> v8::Date::New(double time) {
+ return New(Isolate::GetCurrent(), time);
+}
+
+
double v8::Date::ValueOf() const {
i::Isolate* isolate = i::Isolate::Current();
LOG_API(isolate, "Date::NumberValue");
@@ -5884,22 +5956,22 @@
}
-void v8::Date::DateTimeConfigurationChangeNotification() {
- i::Isolate* isolate = i::Isolate::Current();
- ON_BAILOUT(isolate, "v8::Date::DateTimeConfigurationChangeNotification()",
+void v8::Date::DateTimeConfigurationChangeNotification(Isolate* isolate) {
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ ON_BAILOUT(i_isolate, "v8::Date::DateTimeConfigurationChangeNotification()",
return);
- LOG_API(isolate, "Date::DateTimeConfigurationChangeNotification");
- ENTER_V8(isolate);
+ LOG_API(i_isolate, "Date::DateTimeConfigurationChangeNotification");
+ ENTER_V8(i_isolate);
- isolate->date_cache()->ResetDateCache();
+ i_isolate->date_cache()->ResetDateCache();
- i::HandleScope scope(isolate);
+ i::HandleScope scope(i_isolate);
// Get the function ResetDateCache (defined in date.js).
i::Handle<i::String> func_name_str =
- isolate->factory()->InternalizeOneByteString(
+ i_isolate->factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR("ResetDateCache"));
i::MaybeObject* result =
- isolate->js_builtins_object()->GetProperty(*func_name_str);
+ i_isolate->js_builtins_object()->GetProperty(*func_name_str);
i::Object* object_func;
if (!result->ToObject(&object_func)) {
return;
@@ -5912,7 +5984,7 @@
// Call ResetDateCache(0 but expect no exceptions:
bool caught_exception = false;
i::Execution::TryCall(func,
- isolate->js_builtins_object(),
+ i_isolate->js_builtins_object(),
0,
NULL,
&caught_exception);
@@ -5920,6 +5992,11 @@
}
+void v8::Date::DateTimeConfigurationChangeNotification() {
+ DateTimeConfigurationChangeNotification(Isolate::GetCurrent());
+}
+
+
static i::Handle<i::String> RegExpFlagsToString(RegExp::Flags flags) {
i::Isolate* isolate = i::Isolate::Current();
uint8_t flags_buf[3];
@@ -5971,20 +6048,25 @@
}
-Local<v8::Array> v8::Array::New(int length) {
- i::Isolate* isolate = i::Isolate::Current();
- EnsureInitializedForIsolate(isolate, "v8::Array::New()");
- LOG_API(isolate, "Array::New");
- ENTER_V8(isolate);
+Local<v8::Array> v8::Array::New(Isolate* isolate, int length) {
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ EnsureInitializedForIsolate(i_isolate, "v8::Array::New()");
+ LOG_API(i_isolate, "Array::New");
+ ENTER_V8(i_isolate);
int real_length = length > 0 ? length : 0;
- i::Handle<i::JSArray> obj = isolate->factory()->NewJSArray(real_length);
+ i::Handle<i::JSArray> obj = i_isolate->factory()->NewJSArray(real_length);
i::Handle<i::Object> length_obj =
- isolate->factory()->NewNumberFromInt(real_length);
+ i_isolate->factory()->NewNumberFromInt(real_length);
obj->set_length(*length_obj);
return Utils::ToLocal(obj);
}
+Local<v8::Array> v8::Array::New(int length) {
+ return New(Isolate::GetCurrent(), length);
+}
+
+
uint32_t v8::Array::Length() const {
i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
i::Object* length = obj->length();
@@ -6068,27 +6150,38 @@
}
-Local<ArrayBuffer> v8::ArrayBuffer::New(size_t byte_length) {
- i::Isolate* isolate = i::Isolate::Current();
- EnsureInitializedForIsolate(isolate, "v8::ArrayBuffer::New(size_t)");
- LOG_API(isolate, "v8::ArrayBuffer::New(size_t)");
- ENTER_V8(isolate);
+Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* isolate, size_t byte_length) {
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ EnsureInitializedForIsolate(i_isolate, "v8::ArrayBuffer::New(size_t)");
+ LOG_API(i_isolate, "v8::ArrayBuffer::New(size_t)");
+ ENTER_V8(i_isolate);
i::Handle<i::JSArrayBuffer> obj =
- isolate->factory()->NewJSArrayBuffer();
- i::Runtime::SetupArrayBufferAllocatingData(isolate, obj, byte_length);
+ i_isolate->factory()->NewJSArrayBuffer();
+ i::Runtime::SetupArrayBufferAllocatingData(i_isolate, obj, byte_length);
+ return Utils::ToLocal(obj);
+}
+
+
+Local<ArrayBuffer> v8::ArrayBuffer::New(size_t byte_length) {
+ return New(Isolate::GetCurrent(), byte_length);
+}
+
+
+Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* isolate, void* data,
+ size_t byte_length) {
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ EnsureInitializedForIsolate(i_isolate, "v8::ArrayBuffer::New(void*, size_t)");
+ LOG_API(i_isolate, "v8::ArrayBuffer::New(void*, size_t)");
+ ENTER_V8(i_isolate);
+ i::Handle<i::JSArrayBuffer> obj =
+ i_isolate->factory()->NewJSArrayBuffer();
+ i::Runtime::SetupArrayBuffer(i_isolate, obj, true, data, byte_length);
return Utils::ToLocal(obj);
}
Local<ArrayBuffer> v8::ArrayBuffer::New(void* data, size_t byte_length) {
- i::Isolate* isolate = i::Isolate::Current();
- EnsureInitializedForIsolate(isolate, "v8::ArrayBuffer::New(void*, size_t)");
- LOG_API(isolate, "v8::ArrayBuffer::New(void*, size_t)");
- ENTER_V8(isolate);
- i::Handle<i::JSArrayBuffer> obj =
- isolate->factory()->NewJSArrayBuffer();
- i::Runtime::SetupArrayBuffer(isolate, obj, true, data, byte_length);
- return Utils::ToLocal(obj);
+ return New(Isolate::GetCurrent(), data, byte_length);
}
@@ -6280,18 +6373,28 @@
Local<Integer> v8::Integer::New(int32_t value) {
i::Isolate* isolate = i::Isolate::UncheckedCurrent();
EnsureInitializedForIsolate(isolate, "v8::Integer::New()");
- return v8::Integer::New(value, reinterpret_cast<Isolate*>(isolate));
+ return v8::Integer::New(reinterpret_cast<Isolate*>(isolate), value);
}
Local<Integer> Integer::NewFromUnsigned(uint32_t value) {
i::Isolate* isolate = i::Isolate::Current();
EnsureInitializedForIsolate(isolate, "v8::Integer::NewFromUnsigned()");
- return Integer::NewFromUnsigned(value, reinterpret_cast<Isolate*>(isolate));
+ return Integer::NewFromUnsigned(reinterpret_cast<Isolate*>(isolate), value);
}
Local<Integer> v8::Integer::New(int32_t value, Isolate* isolate) {
+ return Integer::New(isolate, value);
+}
+
+
+Local<Integer> v8::Integer::NewFromUnsigned(uint32_t value, Isolate* isolate) {
+ return Integer::NewFromUnsigned(isolate, value);
+}
+
+
+Local<Integer> v8::Integer::New(Isolate* isolate, int32_t value) {
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
ASSERT(internal_isolate->IsInitialized());
if (i::Smi::IsValid(value)) {
@@ -6304,7 +6407,7 @@
}
-Local<Integer> v8::Integer::NewFromUnsigned(uint32_t value, Isolate* isolate) {
+Local<Integer> v8::Integer::NewFromUnsigned(Isolate* isolate, uint32_t value) {
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
ASSERT(internal_isolate->IsInitialized());
bool fits_into_int32_t = (value & (1 << 31)) == 0;
diff --git a/src/arm/assembler-arm-inl.h b/src/arm/assembler-arm-inl.h
index 24c5cca..3399958 100644
--- a/src/arm/assembler-arm-inl.h
+++ b/src/arm/assembler-arm-inl.h
@@ -457,12 +457,6 @@
}
-void Assembler::set_external_target_at(Address constant_pool_entry,
- Address target) {
- Memory::Address_at(constant_pool_entry) = target;
-}
-
-
static Instr EncodeMovwImmediate(uint32_t immediate) {
ASSERT(immediate < 0x10000);
return ((immediate & 0xf000) << 4) | (immediate & 0xfff);
diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h
index 137dd73..afb0c62 100644
--- a/src/arm/assembler-arm.h
+++ b/src/arm/assembler-arm.h
@@ -803,11 +803,6 @@
inline static void deserialization_set_special_target_at(
Address constant_pool_entry, Address target);
- // This sets the branch destination (which is in the constant pool on ARM).
- // This is for calls and branches to runtime code.
- inline static void set_external_target_at(Address constant_pool_entry,
- Address target);
-
// Here we are patching the address in the constant pool, not the actual call
// instruction. The address in the constant pool is the same size as a
// pointer.
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index 3473445..bfe6da0 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -77,7 +77,7 @@
descriptor->register_param_count_ = 3;
descriptor->register_params_ = registers;
descriptor->deoptimization_handler_ =
- Runtime::FunctionForId(Runtime::kCreateArrayLiteral)->entry;
+ Runtime::FunctionForId(Runtime::kCreateArrayLiteralStubBailout)->entry;
}
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 4a39970..15bfba3 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -1770,6 +1770,10 @@
Comment cmnt(masm_, "[ ArrayLiteral");
expr->BuildConstantElements(isolate());
+ int flags = expr->depth() == 1
+ ? ArrayLiteral::kShallowElements
+ : ArrayLiteral::kNoFlags;
+
ZoneList<Expression*>* subexprs = expr->values();
int length = subexprs->length();
Handle<FixedArray> constant_elements = expr->constant_elements();
@@ -1795,8 +1799,9 @@
isolate()->counters()->cow_arrays_created_stub(), 1, r1, r2);
} else if (expr->depth() > 1 || Serializer::enabled() ||
length > FastCloneShallowArrayStub::kMaximumClonedLength) {
- __ Push(r3, r2, r1);
- __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
+ __ mov(r0, Operand(Smi::FromInt(flags)));
+ __ Push(r3, r2, r1, r0);
+ __ CallRuntime(Runtime::kCreateArrayLiteral, 4);
} else {
ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) ||
FLAG_smi_only_arrays);
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index eeffc16..71c9dda 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -1667,6 +1667,15 @@
result = AssignEnvironment(result);
}
return result;
+ } else if (instr->representation().IsExternal()) {
+ ASSERT(instr->left()->representation().IsExternal());
+ ASSERT(instr->right()->representation().IsInteger32());
+ ASSERT(!instr->CheckFlag(HValue::kCanOverflow));
+ LOperand* left = UseRegisterAtStart(instr->left());
+ LOperand* right = UseOrConstantAtStart(instr->right());
+ LAddI* add = new(zone()) LAddI(left, right);
+ LInstruction* result = DefineAsRegister(add);
+ return result;
} else if (instr->representation().IsDouble()) {
if (instr->left()->IsMul()) {
return DoMultiplyAdd(HMul::cast(instr->left()), instr->right());
@@ -2561,7 +2570,7 @@
LInstruction* goto_instr = CheckElideControlInstruction(instr);
if (goto_instr != NULL) return goto_instr;
- return new(zone()) LTypeofIsAndBranch(UseTempRegister(instr->value()));
+ return new(zone()) LTypeofIsAndBranch(UseRegister(instr->value()));
}
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 4b05db1..6dadef0 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -5557,22 +5557,21 @@
Register scratch = scratch0();
if (type_name->Equals(heap()->number_string())) {
__ JumpIfSmi(input, true_label);
- __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset));
- __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
- __ cmp(input, Operand(ip));
+ __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
+ __ CompareRoot(scratch, Heap::kHeapNumberMapRootIndex);
final_branch_condition = eq;
} else if (type_name->Equals(heap()->string_string())) {
__ JumpIfSmi(input, false_label);
- __ CompareObjectType(input, input, scratch, FIRST_NONSTRING_TYPE);
+ __ CompareObjectType(input, scratch, no_reg, FIRST_NONSTRING_TYPE);
__ b(ge, false_label);
- __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
- __ tst(ip, Operand(1 << Map::kIsUndetectable));
+ __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
+ __ tst(scratch, Operand(1 << Map::kIsUndetectable));
final_branch_condition = eq;
} else if (type_name->Equals(heap()->symbol_string())) {
__ JumpIfSmi(input, false_label);
- __ CompareObjectType(input, input, scratch, SYMBOL_TYPE);
+ __ CompareObjectType(input, scratch, no_reg, SYMBOL_TYPE);
final_branch_condition = eq;
} else if (type_name->Equals(heap()->boolean_string())) {
@@ -5590,33 +5589,35 @@
__ b(eq, true_label);
__ JumpIfSmi(input, false_label);
// Check for undetectable objects => true.
- __ ldr(input, FieldMemOperand(input, HeapObject::kMapOffset));
- __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
- __ tst(ip, Operand(1 << Map::kIsUndetectable));
+ __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
+ __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
+ __ tst(scratch, Operand(1 << Map::kIsUndetectable));
final_branch_condition = ne;
} else if (type_name->Equals(heap()->function_string())) {
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
+ Register type_reg = scratch;
__ JumpIfSmi(input, false_label);
- __ CompareObjectType(input, scratch, input, JS_FUNCTION_TYPE);
+ __ CompareObjectType(input, scratch, type_reg, JS_FUNCTION_TYPE);
__ b(eq, true_label);
- __ cmp(input, Operand(JS_FUNCTION_PROXY_TYPE));
+ __ cmp(type_reg, Operand(JS_FUNCTION_PROXY_TYPE));
final_branch_condition = eq;
} else if (type_name->Equals(heap()->object_string())) {
+ Register map = scratch;
__ JumpIfSmi(input, false_label);
if (!FLAG_harmony_typeof) {
__ CompareRoot(input, Heap::kNullValueRootIndex);
__ b(eq, true_label);
}
- __ CompareObjectType(input, input, scratch,
- FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
- __ b(lt, false_label);
- __ CompareInstanceType(input, scratch, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
- __ b(gt, false_label);
+ __ CheckObjectTypeRange(input,
+ map,
+ FIRST_NONCALLABLE_SPEC_OBJECT_TYPE,
+ LAST_NONCALLABLE_SPEC_OBJECT_TYPE,
+ false_label);
// Check for undetectable objects => false.
- __ ldrb(ip, FieldMemOperand(input, Map::kBitFieldOffset));
- __ tst(ip, Operand(1 << Map::kIsUndetectable));
+ __ ldrb(scratch, FieldMemOperand(map, Map::kBitFieldOffset));
+ __ tst(scratch, Operand(1 << Map::kIsUndetectable));
final_branch_condition = eq;
} else {
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index 65962e7..8bb1cb1 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -2022,14 +2022,36 @@
Register map,
Register type_reg,
InstanceType type) {
+ const Register temp = type_reg.is(no_reg) ? ip : type_reg;
+
ldr(map, FieldMemOperand(object, HeapObject::kMapOffset));
- CompareInstanceType(map, type_reg, type);
+ CompareInstanceType(map, temp, type);
+}
+
+
+void MacroAssembler::CheckObjectTypeRange(Register object,
+ Register map,
+ InstanceType min_type,
+ InstanceType max_type,
+ Label* false_label) {
+ STATIC_ASSERT(Map::kInstanceTypeOffset < 4096);
+ STATIC_ASSERT(LAST_TYPE < 256);
+ ldr(map, FieldMemOperand(object, HeapObject::kMapOffset));
+ ldrb(ip, FieldMemOperand(map, Map::kInstanceTypeOffset));
+ sub(ip, ip, Operand(min_type));
+ cmp(ip, Operand(max_type - min_type));
+ b(hi, false_label);
}
void MacroAssembler::CompareInstanceType(Register map,
Register type_reg,
InstanceType type) {
+ // Registers map and type_reg can be ip. These two lines assert
+ // that ip can be used with the two instructions (the constants
+ // will never need ip).
+ STATIC_ASSERT(Map::kInstanceTypeOffset < 4096);
+ STATIC_ASSERT(LAST_TYPE < 256);
ldrb(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
cmp(type_reg, Operand(type));
}
diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
index 5e20eec..467a1ac 100644
--- a/src/arm/macro-assembler-arm.h
+++ b/src/arm/macro-assembler-arm.h
@@ -845,11 +845,21 @@
// are the same register). It leaves the heap object in the heap_object
// register unless the heap_object register is the same register as one of the
// other registers.
+ // Type_reg can be no_reg. In that case ip is used.
void CompareObjectType(Register heap_object,
Register map,
Register type_reg,
InstanceType type);
+ // Compare object type for heap object. Branch to false_label if type
+ // is lower than min_type or greater than max_type.
+ // Load map into the register map.
+ void CheckObjectTypeRange(Register heap_object,
+ Register map,
+ InstanceType min_type,
+ InstanceType max_type,
+ Label* false_label);
+
// Compare instance type in a map. map contains a valid map object whose
// object type should be compared with the given type. This both
// sets the flags and leaves the object type in the type_reg register.
diff --git a/src/arm/simulator-arm.h b/src/arm/simulator-arm.h
index e392c5c..0af5162 100644
--- a/src/arm/simulator-arm.h
+++ b/src/arm/simulator-arm.h
@@ -269,7 +269,7 @@
// Checks if the current instruction should be executed based on its
// condition bits.
- bool ConditionallyExecute(Instruction* instr);
+ inline bool ConditionallyExecute(Instruction* instr);
// Helper functions to set the conditional flags in the architecture state.
void SetNZFlags(int32_t val);
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index 9b2ba53..00ea079 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -798,17 +798,12 @@
Register receiver,
Register holder,
Register name,
- Handle<JSObject> holder_obj) {
+ Handle<JSObject> holder_obj,
+ IC::UtilityId id) {
PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
-
- ExternalReference ref =
- ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly),
- masm->isolate());
- __ mov(r0, Operand(StubCache::kInterceptorArgsLength));
- __ mov(r1, Operand(ref));
-
- CEntryStub stub(1);
- __ CallStub(&stub);
+ __ CallExternalReference(
+ ExternalReference(IC_Utility(id), masm->isolate()),
+ StubCache::kInterceptorArgsLength);
}
@@ -1113,11 +1108,11 @@
FrameScope scope(masm, StackFrame::INTERNAL);
// Save the name_ register across the call.
__ push(name_);
- PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder);
- __ CallExternalReference(
- ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall),
- masm->isolate()),
- StubCache::kInterceptorArgsLength);
+
+ CompileCallLoadPropertyWithInterceptor(
+ masm, receiver, holder, name_, interceptor_holder,
+ IC::kLoadPropertyWithInterceptorForCall);
+
// Restore the name_ register.
__ pop(name_);
// Leave the internal frame.
@@ -1132,11 +1127,9 @@
{
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(holder, name_);
- CompileCallLoadPropertyWithInterceptor(masm,
- receiver,
- holder,
- name_,
- holder_obj);
+ CompileCallLoadPropertyWithInterceptor(
+ masm, receiver, holder, name_, holder_obj,
+ IC::kLoadPropertyWithInterceptorOnly);
__ pop(name_); // Restore the name.
__ pop(receiver); // Restore the holder.
}
@@ -1503,11 +1496,10 @@
// Invoke an interceptor. Note: map checks from receiver to
// interceptor's holder has been compiled before (see a caller
// of this method.)
- CompileCallLoadPropertyWithInterceptor(masm(),
- receiver(),
- holder_reg,
- this->name(),
- interceptor_holder);
+ CompileCallLoadPropertyWithInterceptor(
+ masm(), receiver(), holder_reg, this->name(), interceptor_holder,
+ IC::kLoadPropertyWithInterceptorOnly);
+
// Check if interceptor provided a value for property. If it's
// the case, return immediately.
Label interceptor_failed;
diff --git a/src/ast.h b/src/ast.h
index e3fc053..4158907 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -1604,6 +1604,12 @@
// Populate the constant elements fixed array.
void BuildConstantElements(Isolate* isolate);
+ enum Flags {
+ kNoFlags = 0,
+ kShallowElements = 1,
+ kDisableMementos = 1 << 1
+ };
+
protected:
ArrayLiteral(Isolate* isolate,
ZoneList<Expression*>* values,
diff --git a/src/debug.cc b/src/debug.cc
index f3c3764..23495c8 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -3137,7 +3137,7 @@
v8::Local<v8::Function> fun =
v8::Local<v8::Function>::Cast(api_exec_state->Get(fun_name));
- v8::Handle<v8::Boolean> running = v8::Boolean::New(auto_continue);
+ v8::Handle<v8::Boolean> running = v8::Boolean::New(isolate, auto_continue);
static const int kArgc = 1;
v8::Handle<Value> argv[kArgc] = { running };
cmd_processor = v8::Local<v8::Object>::Cast(
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index fec9ee5..483d1e3 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -1579,7 +1579,8 @@
// Compute the function template for the native function.
Handle<String> name = expr->name();
v8::Handle<v8::FunctionTemplate> fun_template =
- expr->extension()->GetNativeFunction(v8::Utils::ToLocal(name));
+ expr->extension()->GetNativeFunctionTemplate(
+ reinterpret_cast<v8::Isolate*>(isolate()), v8::Utils::ToLocal(name));
ASSERT(!fun_template.IsEmpty());
// Instantiate the function and create a shared function info from it.
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index e816471..5675c55 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -1262,6 +1262,26 @@
}
+Representation HAdd::RepresentationFromInputs() {
+ Representation left_rep = left()->representation();
+ if (left_rep.IsExternal()) {
+ return Representation::External();
+ }
+ return HArithmeticBinaryOperation::RepresentationFromInputs();
+}
+
+
+Representation HAdd::RequiredInputRepresentation(int index) {
+ if (index == 2) {
+ Representation left_rep = left()->representation();
+ if (left_rep.IsExternal()) {
+ return Representation::Integer32();
+ }
+ }
+ return HArithmeticBinaryOperation::RequiredInputRepresentation(index);
+}
+
+
static bool IsIdentityOperation(HValue* arg1, HValue* arg2, int32_t identity) {
return arg1->representation().IsSpecialization() &&
arg2->EqualsInteger32Constant(identity);
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index fba23fa..eac3c51 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -4732,8 +4732,9 @@
// Add is only commutative if two integer values are added and not if two
// tagged values are added (because it might be a String concatenation).
+ // We also do not commute (pointer + offset).
virtual bool IsCommutative() const V8_OVERRIDE {
- return !representation().IsTagged();
+ return !representation().IsTagged() && !representation().IsExternal();
}
virtual HValue* EnsureAndPropagateNotMinusZero(
@@ -4769,6 +4770,10 @@
}
}
+ virtual Representation RepresentationFromInputs() V8_OVERRIDE;
+
+ virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE;
+
DECLARE_CONCRETE_INSTRUCTION(Add)
protected:
@@ -6062,6 +6067,43 @@
// Create an access for the payload of a Cell or JSGlobalPropertyCell.
static HObjectAccess ForCellPayload(Isolate* isolate);
+ static HObjectAccess ForJSTypedArrayLength() {
+ return HObjectAccess::ForJSObjectOffset(JSTypedArray::kLengthOffset);
+ }
+
+ static HObjectAccess ForJSArrayBufferBackingStore() {
+ return HObjectAccess::ForJSObjectOffset(
+ JSArrayBuffer::kBackingStoreOffset, Representation::External());
+ }
+
+ static HObjectAccess ForExternalArrayExternalPointer() {
+ return HObjectAccess::ForJSObjectOffset(
+ ExternalArray::kExternalPointerOffset, Representation::External());
+ }
+
+ static HObjectAccess ForJSArrayBufferViewWeakNext() {
+ return HObjectAccess::ForJSObjectOffset(JSArrayBufferView::kWeakNextOffset);
+ }
+
+ static HObjectAccess ForJSArrayBufferWeakFirstView() {
+ return HObjectAccess::ForJSObjectOffset(
+ JSArrayBuffer::kWeakFirstViewOffset);
+ }
+
+ static HObjectAccess ForJSArrayBufferViewBuffer() {
+ return HObjectAccess::ForJSObjectOffset(JSArrayBufferView::kBufferOffset);
+ }
+
+ static HObjectAccess ForJSArrayBufferViewByteOffset() {
+ return HObjectAccess::ForJSObjectOffset(
+ JSArrayBufferView::kByteOffsetOffset);
+ }
+
+ static HObjectAccess ForJSArrayBufferViewByteLength() {
+ return HObjectAccess::ForJSObjectOffset(
+ JSArrayBufferView::kByteLengthOffset);
+ }
+
void PrintTo(StringStream* stream);
inline bool Equals(HObjectAccess that) const {
@@ -6478,6 +6520,8 @@
} else if (field_representation().IsDouble() ||
field_representation().IsSmi()) {
return field_representation();
+ } else if (field_representation().IsExternal()) {
+ return Representation::External();
}
}
return Representation::Tagged();
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 3e08b69..634acd7 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -58,6 +58,7 @@
#include "hydrogen-uint32-analysis.h"
#include "lithium-allocator.h"
#include "parser.h"
+#include "runtime.h"
#include "scopeinfo.h"
#include "scopes.h"
#include "stub-cache.h"
@@ -5107,10 +5108,15 @@
// pass an empty fixed array to the runtime function instead.
Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array();
int literal_index = expr->literal_index();
+ int flags = expr->depth() == 1
+ ? ArrayLiteral::kShallowElements
+ : ArrayLiteral::kNoFlags;
+ flags |= ArrayLiteral::kDisableMementos;
Add<HPushArgument>(Add<HConstant>(literals));
Add<HPushArgument>(Add<HConstant>(literal_index));
Add<HPushArgument>(Add<HConstant>(constants));
+ Add<HPushArgument>(Add<HConstant>(flags));
// TODO(mvstanton): Consider a flag to turn off creation of any
// AllocationMementos for this call: we are in crankshaft and should have
@@ -5118,7 +5124,7 @@
Runtime::FunctionId function_id = Runtime::kCreateArrayLiteral;
literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
Runtime::FunctionForId(function_id),
- 3);
+ 4);
// De-opt if elements kind changed from boilerplate_elements_kind.
Handle<Map> map = Handle<Map>(boilerplate_object->map(), isolate());
@@ -8055,6 +8061,42 @@
#undef INLINE_FUNCTION_GENERATOR_ADDRESS
+template <class ViewClass>
+void HGraphBuilder::BuildArrayBufferViewInitialization(
+ HValue* obj,
+ HValue* buffer,
+ HValue* byte_offset,
+ HValue* byte_length) {
+
+ for (int offset = ViewClass::kSize;
+ offset < ViewClass::kSizeWithInternalFields;
+ offset += kPointerSize) {
+ Add<HStoreNamedField>(obj,
+ HObjectAccess::ForJSObjectOffset(offset),
+ Add<HConstant>(static_cast<int32_t>(0)));
+ }
+
+ Add<HStoreNamedField>(
+ obj,
+ HObjectAccess::ForJSArrayBufferViewBuffer(), buffer);
+ Add<HStoreNamedField>(
+ obj,
+ HObjectAccess::ForJSArrayBufferViewByteOffset(),
+ byte_offset);
+ Add<HStoreNamedField>(
+ obj,
+ HObjectAccess::ForJSArrayBufferViewByteLength(),
+ byte_length);
+
+ HObjectAccess weak_first_view_access =
+ HObjectAccess::ForJSArrayBufferWeakFirstView();
+ Add<HStoreNamedField>(obj,
+ HObjectAccess::ForJSArrayBufferViewWeakNext(),
+ Add<HLoadNamedField>(buffer, weak_first_view_access));
+ Add<HStoreNamedField>(buffer, weak_first_view_access, obj);
+}
+
+
void HOptimizedGraphBuilder::VisitDataViewInitialize(
CallRuntime* expr) {
ZoneList<Expression*>* arguments = expr->arguments();
@@ -8073,31 +8115,127 @@
CHECK_ALIVE(VisitForValue(arguments->at(3)));
HValue* byte_length = Pop();
- for (int offset = JSDataView::kSize;
- offset < JSDataView::kSizeWithInternalFields;
- offset += kPointerSize) {
- Add<HStoreNamedField>(obj,
- HObjectAccess::ForJSObjectOffset(offset),
- Add<HConstant>(static_cast<int32_t>(0)));
+ BuildArrayBufferViewInitialization<JSDataView>(
+ obj, buffer, byte_offset, byte_length);
+}
+
+
+void HOptimizedGraphBuilder::VisitTypedArrayInitialize(
+ CallRuntime* expr) {
+ ZoneList<Expression*>* arguments = expr->arguments();
+
+ NoObservableSideEffectsScope scope(this);
+ static const int kObjectArg = 0;
+ static const int kArrayIdArg = 1;
+ static const int kBufferArg = 2;
+ static const int kByteOffsetArg = 3;
+ static const int kByteLengthArg = 4;
+ static const int kArgsLength = 5;
+ ASSERT(arguments->length() == kArgsLength);
+
+
+ CHECK_ALIVE(VisitForValue(arguments->at(kObjectArg)));
+ HValue* obj = Pop();
+
+ ASSERT(arguments->at(kArrayIdArg)->node_type() == AstNode::kLiteral);
+ Handle<Object> value =
+ static_cast<Literal*>(arguments->at(kArrayIdArg))->value();
+ ASSERT(value->IsSmi());
+ int array_id = Smi::cast(*value)->value();
+
+ CHECK_ALIVE(VisitForValue(arguments->at(kBufferArg)));
+ HValue* buffer = Pop();
+
+ HValue* byte_offset;
+ bool is_zero_byte_offset;
+
+ if (arguments->at(kByteOffsetArg)->node_type() == AstNode::kLiteral
+ && Smi::FromInt(0) ==
+ *static_cast<Literal*>(arguments->at(kByteOffsetArg))->value()) {
+ byte_offset = Add<HConstant>(static_cast<int32_t>(0));
+ is_zero_byte_offset = true;
+ } else {
+ CHECK_ALIVE(VisitForValue(arguments->at(kByteOffsetArg)));
+ byte_offset = Pop();
+ is_zero_byte_offset = false;
}
- Add<HStoreNamedField>(obj,
- HObjectAccess::ForJSObjectOffset(JSDataView::kBufferOffset), buffer);
- Add<HStoreNamedField>(obj,
- HObjectAccess::ForJSObjectOffset(JSDataView::kByteOffsetOffset),
- byte_offset);
- Add<HStoreNamedField>(obj,
- HObjectAccess::ForJSObjectOffset(JSDataView::kByteLengthOffset),
- byte_length);
+ CHECK_ALIVE(VisitForValue(arguments->at(kByteLengthArg)));
+ HValue* byte_length = Pop();
- Add<HStoreNamedField>(obj,
- HObjectAccess::ForJSObjectOffset(JSDataView::kWeakNextOffset),
- Add<HLoadNamedField>(buffer,
- HObjectAccess::ForJSObjectOffset(
- JSArrayBuffer::kWeakFirstViewOffset)));
- Add<HStoreNamedField>(buffer,
- HObjectAccess::ForJSObjectOffset(JSArrayBuffer::kWeakFirstViewOffset),
- obj);
+ IfBuilder byte_offset_smi(this);
+
+ if (!is_zero_byte_offset) {
+ byte_offset_smi.If<HIsSmiAndBranch>(byte_offset);
+ byte_offset_smi.Then();
+ }
+
+ { // byte_offset is Smi.
+ BuildArrayBufferViewInitialization<JSTypedArray>(
+ obj, buffer, byte_offset, byte_length);
+
+ ExternalArrayType array_type = kExternalByteArray; // Bogus initialization.
+ size_t element_size = 1; // Bogus initialization.
+ Runtime::ArrayIdToTypeAndSize(array_id, &array_type, &element_size);
+
+ HInstruction* length = AddUncasted<HDiv>(byte_length,
+ Add<HConstant>(static_cast<int32_t>(element_size)));
+
+ Add<HStoreNamedField>(obj,
+ HObjectAccess::ForJSTypedArrayLength(),
+ length);
+
+ HValue* elements =
+ Add<HAllocate>(
+ Add<HConstant>(ExternalArray::kAlignedSize),
+ HType::JSArray(),
+ NOT_TENURED,
+ static_cast<InstanceType>(FIRST_EXTERNAL_ARRAY_TYPE + array_type));
+
+ Handle<Map> external_array_map(
+ isolate()->heap()->MapForExternalArrayType(array_type));
+ Add<HStoreNamedField>(elements,
+ HObjectAccess::ForMap(),
+ Add<HConstant>(external_array_map));
+
+ HValue* backing_store = Add<HLoadNamedField>(
+ buffer, HObjectAccess::ForJSArrayBufferBackingStore());
+
+ HValue* typed_array_start;
+ if (is_zero_byte_offset) {
+ typed_array_start = backing_store;
+ } else {
+ HInstruction* external_pointer =
+ AddUncasted<HAdd>(backing_store, byte_offset);
+ // Arguments are checked prior to call to TypedArrayInitialize,
+ // including byte_offset.
+ external_pointer->ClearFlag(HValue::kCanOverflow);
+ typed_array_start = external_pointer;
+ }
+
+ Add<HStoreNamedField>(elements,
+ HObjectAccess::ForExternalArrayExternalPointer(),
+ typed_array_start);
+ Add<HStoreNamedField>(elements,
+ HObjectAccess::ForFixedArrayLength(),
+ length);
+ Add<HStoreNamedField>(
+ obj, HObjectAccess::ForElementsPointer(), elements);
+ }
+
+ if (!is_zero_byte_offset) {
+ byte_offset_smi.Else();
+ { // byte_offset is not Smi.
+ Push(Add<HPushArgument>(obj));
+ VisitArgument(arguments->at(kArrayIdArg));
+ Push(Add<HPushArgument>(buffer));
+ Push(Add<HPushArgument>(byte_offset));
+ Push(Add<HPushArgument>(byte_length));
+ Add<HCallRuntime>(expr->name(), expr->function(), kArgsLength);
+ Drop(kArgsLength);
+ }
+ }
+ byte_offset_smi.End();
}
@@ -8116,6 +8254,16 @@
return VisitDataViewInitialize(expr);
}
+ if (function->function_id == Runtime::kTypedArrayInitialize) {
+ return VisitTypedArrayInitialize(expr);
+ }
+
+ if (function->function_id == Runtime::kMaxSmi) {
+ ASSERT(expr->arguments()->length() == 0);
+ HConstant* max_smi = New<HConstant>(static_cast<int32_t>(Smi::kMaxValue));
+ return ast_context()->ReturnInstruction(max_smi, expr->id());
+ }
+
if (function->intrinsic_type == Runtime::INLINE) {
ASSERT(expr->name()->length() > 0);
ASSERT(expr->name()->Get(0) == '_');
@@ -9175,7 +9323,7 @@
HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
Handle<JSObject> boilerplate_object,
- AllocationSiteContext* site_context) {
+ AllocationSiteUsageContext* site_context) {
NoObservableSideEffectsScope no_effects(this);
InstanceType instance_type = boilerplate_object->map()->instance_type();
ASSERT(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE);
@@ -9268,7 +9416,7 @@
void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
Handle<JSObject> boilerplate_object,
HInstruction* object,
- AllocationSiteContext* site_context) {
+ AllocationSiteUsageContext* site_context) {
Handle<DescriptorArray> descriptors(
boilerplate_object->map()->instance_descriptors());
int limit = boilerplate_object->map()->NumberOfOwnDescriptors();
@@ -9340,7 +9488,7 @@
Handle<JSObject> boilerplate_object,
Handle<FixedArrayBase> elements,
HValue* object_elements,
- AllocationSiteContext* site_context) {
+ AllocationSiteUsageContext* site_context) {
ElementsKind kind = boilerplate_object->map()->elements_kind();
int elements_length = elements->length();
HValue* object_elements_length = Add<HConstant>(elements_length);
@@ -9381,7 +9529,7 @@
Handle<FixedArrayBase> elements,
ElementsKind kind,
HValue* object_elements,
- AllocationSiteContext* site_context) {
+ AllocationSiteUsageContext* site_context) {
HInstruction* boilerplate_elements = Add<HConstant>(elements);
int elements_length = elements->length();
Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
diff --git a/src/hydrogen.h b/src/hydrogen.h
index e0c5066..bd42896 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -1736,6 +1736,12 @@
position_ = position;
}
+ template <typename ViewClass>
+ void BuildArrayBufferViewInitialization(HValue* obj,
+ HValue* buffer,
+ HValue* byte_offset,
+ HValue* byte_length);
+
private:
HGraphBuilder();
@@ -2195,6 +2201,8 @@
SmallMapList* types,
Handle<String> name);
+ void VisitTypedArrayInitialize(CallRuntime* expr);
+
bool IsCallNewArrayInlineable(CallNew* expr);
void BuildInlinedCallNewArray(CallNew* expr);
@@ -2403,7 +2411,7 @@
HInstruction* BuildThisFunction();
HInstruction* BuildFastLiteral(Handle<JSObject> boilerplate_object,
- AllocationSiteContext* site_context);
+ AllocationSiteUsageContext* site_context);
void BuildEmitObjectHeader(Handle<JSObject> boilerplate_object,
HInstruction* object);
@@ -2414,12 +2422,12 @@
void BuildEmitInObjectProperties(Handle<JSObject> boilerplate_object,
HInstruction* object,
- AllocationSiteContext* site_context);
+ AllocationSiteUsageContext* site_context);
void BuildEmitElements(Handle<JSObject> boilerplate_object,
Handle<FixedArrayBase> elements,
HValue* object_elements,
- AllocationSiteContext* site_context);
+ AllocationSiteUsageContext* site_context);
void BuildEmitFixedDoubleArray(Handle<FixedArrayBase> elements,
ElementsKind kind,
@@ -2428,7 +2436,7 @@
void BuildEmitFixedArray(Handle<FixedArrayBase> elements,
ElementsKind kind,
HValue* object_elements,
- AllocationSiteContext* site_context);
+ AllocationSiteUsageContext* site_context);
void AddCheckPrototypeMaps(Handle<JSObject> holder,
Handle<Map> receiver_map);
diff --git a/src/ia32/assembler-ia32.h b/src/ia32/assembler-ia32.h
index ed7b71f..6ed0bc6 100644
--- a/src/ia32/assembler-ia32.h
+++ b/src/ia32/assembler-ia32.h
@@ -638,13 +638,6 @@
set_target_address_at(instruction_payload, target);
}
- // This sets the branch destination (which is in the instruction on x86).
- // This is for calls and branches to runtime code.
- inline static void set_external_target_at(Address instruction_payload,
- Address target) {
- set_target_address_at(instruction_payload, target);
- }
-
static const int kSpecialTargetSize = kPointerSize;
// Distance between the address of the code target in the call instruction
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index f06cc5b..715feca 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -82,7 +82,7 @@
descriptor->register_param_count_ = 3;
descriptor->register_params_ = registers;
descriptor->deoptimization_handler_ =
- Runtime::FunctionForId(Runtime::kCreateArrayLiteral)->entry;
+ Runtime::FunctionForId(Runtime::kCreateArrayLiteralStubBailout)->entry;
}
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index e067c90..909294e 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -1705,6 +1705,10 @@
Comment cmnt(masm_, "[ ArrayLiteral");
expr->BuildConstantElements(isolate());
+ int flags = expr->depth() == 1
+ ? ArrayLiteral::kShallowElements
+ : ArrayLiteral::kNoFlags;
+
ZoneList<Expression*>* subexprs = expr->values();
int length = subexprs->length();
Handle<FixedArray> constant_elements = expr->constant_elements();
@@ -1737,7 +1741,8 @@
__ push(FieldOperand(ebx, JSFunction::kLiteralsOffset));
__ push(Immediate(Smi::FromInt(expr->literal_index())));
__ push(Immediate(constant_elements));
- __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
+ __ push(Immediate(Smi::FromInt(flags)));
+ __ CallRuntime(Runtime::kCreateArrayLiteral, 4);
} else {
ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) ||
FLAG_smi_only_arrays);
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index 5343773..921b5aa 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -1653,6 +1653,21 @@
return result;
} else if (instr->representation().IsDouble()) {
return DoArithmeticD(Token::ADD, instr);
+ } else if (instr->representation().IsExternal()) {
+ ASSERT(instr->left()->representation().IsExternal());
+ ASSERT(instr->right()->representation().IsInteger32());
+ ASSERT(!instr->CheckFlag(HValue::kCanOverflow));
+ bool use_lea = LAddI::UseLea(instr);
+ LOperand* left = UseRegisterAtStart(instr->left());
+ HValue* right_candidate = instr->right();
+ LOperand* right = use_lea
+ ? UseRegisterOrConstantAtStart(right_candidate)
+ : UseOrConstantAtStart(right_candidate);
+ LAddI* add = new(zone()) LAddI(left, right);
+ LInstruction* result = use_lea
+ ? DefineAsRegister(add)
+ : DefineSameAsFirst(add);
+ return result;
} else {
return DoArithmeticT(Token::ADD, instr);
}
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index d26210d..1c98c98 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -405,11 +405,11 @@
Register receiver,
Register holder,
Register name,
- Handle<JSObject> holder_obj) {
+ Handle<JSObject> holder_obj,
+ IC::UtilityId id) {
PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
__ CallExternalReference(
- ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly),
- masm->isolate()),
+ ExternalReference(IC_Utility(id), masm->isolate()),
StubCache::kInterceptorArgsLength);
}
@@ -797,12 +797,9 @@
// Save the name_ register across the call.
__ push(name_);
- PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder);
-
- __ CallExternalReference(
- ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall),
- masm->isolate()),
- StubCache::kInterceptorArgsLength);
+ CompileCallLoadPropertyWithInterceptor(
+ masm, receiver, holder, name_, interceptor_holder,
+ IC::kLoadPropertyWithInterceptorForCall);
// Restore the name_ register.
__ pop(name_);
@@ -820,11 +817,9 @@
__ push(holder); // Save the holder.
__ push(name_); // Save the name.
- CompileCallLoadPropertyWithInterceptor(masm,
- receiver,
- holder,
- name_,
- holder_obj);
+ CompileCallLoadPropertyWithInterceptor(
+ masm, receiver, holder, name_, holder_obj,
+ IC::kLoadPropertyWithInterceptorOnly);
__ pop(name_); // Restore the name.
__ pop(receiver); // Restore the holder.
@@ -1553,11 +1548,9 @@
// Invoke an interceptor. Note: map checks from receiver to
// interceptor's holder has been compiled before (see a caller
// of this method.)
- CompileCallLoadPropertyWithInterceptor(masm(),
- receiver(),
- holder_reg,
- this->name(),
- interceptor_holder);
+ CompileCallLoadPropertyWithInterceptor(
+ masm(), receiver(), holder_reg, this->name(), interceptor_holder,
+ IC::kLoadPropertyWithInterceptorOnly);
// Check if interceptor provided a value for property. If it's
// the case, return immediately.
diff --git a/src/math.js b/src/math.js
index fb7d306..5cbe94a 100644
--- a/src/math.js
+++ b/src/math.js
@@ -74,7 +74,7 @@
// ECMA 262 - 15.8.2.6
function MathCeil(x) {
- return %Math_ceil(TO_NUMBER_INLINE(x));
+ return -MathFloor(-x);
}
// ECMA 262 - 15.8.2.7
@@ -348,6 +348,8 @@
"imul", MathImul
));
+ %SetInlineBuiltinFlag(MathCeil);
+ %SetInlineBuiltinFlag(MathRandom);
%SetInlineBuiltinFlag(MathSin);
%SetInlineBuiltinFlag(MathCos);
%SetInlineBuiltinFlag(MathTan);
diff --git a/src/mips/assembler-mips.h b/src/mips/assembler-mips.h
index 49cce62..d9ef46c 100644
--- a/src/mips/assembler-mips.h
+++ b/src/mips/assembler-mips.h
@@ -537,13 +537,6 @@
target);
}
- // This sets the branch destination.
- // This is for calls and branches to runtime code.
- inline static void set_external_target_at(Address instruction_payload,
- Address target) {
- set_target_address_at(instruction_payload, target);
- }
-
// Size of an instruction.
static const int kInstrSize = sizeof(Instr);
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index 47afeb4..0c5e35c 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -78,7 +78,7 @@
descriptor->register_param_count_ = 3;
descriptor->register_params_ = registers;
descriptor->deoptimization_handler_ =
- Runtime::FunctionForId(Runtime::kCreateArrayLiteral)->entry;
+ Runtime::FunctionForId(Runtime::kCreateArrayLiteralStubBailout)->entry;
}
diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc
index 486eb9d..8b16e6c 100644
--- a/src/mips/full-codegen-mips.cc
+++ b/src/mips/full-codegen-mips.cc
@@ -1780,6 +1780,10 @@
Comment cmnt(masm_, "[ ArrayLiteral");
expr->BuildConstantElements(isolate());
+ int flags = expr->depth() == 1
+ ? ArrayLiteral::kShallowElements
+ : ArrayLiteral::kNoFlags;
+
ZoneList<Expression*>* subexprs = expr->values();
int length = subexprs->length();
@@ -1808,8 +1812,9 @@
1, a1, a2);
} else if (expr->depth() > 1 || Serializer::enabled() ||
length > FastCloneShallowArrayStub::kMaximumClonedLength) {
- __ Push(a3, a2, a1);
- __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
+ __ li(a0, Operand(Smi::FromInt(flags)));
+ __ Push(a3, a2, a1, a0);
+ __ CallRuntime(Runtime::kCreateArrayLiteral, 4);
} else {
ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) ||
FLAG_smi_only_arrays);
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index 34e5838..d26da4a 100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -1587,6 +1587,15 @@
result = AssignEnvironment(result);
}
return result;
+ } else if (instr->representation().IsExternal()) {
+ ASSERT(instr->left()->representation().IsExternal());
+ ASSERT(instr->right()->representation().IsInteger32());
+ ASSERT(!instr->CheckFlag(HValue::kCanOverflow));
+ LOperand* left = UseRegisterAtStart(instr->left());
+ LOperand* right = UseOrConstantAtStart(instr->right());
+ LAddI* add = new(zone()) LAddI(left, right);
+ LInstruction* result = DefineAsRegister(add);
+ return result;
} else if (instr->representation().IsDouble()) {
if (kArchVariant == kMips32r2) {
if (instr->left()->IsMul())
diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc
index a477250..e743701 100644
--- a/src/mips/stub-cache-mips.cc
+++ b/src/mips/stub-cache-mips.cc
@@ -785,17 +785,12 @@
Register receiver,
Register holder,
Register name,
- Handle<JSObject> holder_obj) {
+ Handle<JSObject> holder_obj,
+ IC::UtilityId id) {
PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
-
- ExternalReference ref =
- ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly),
- masm->isolate());
- __ PrepareCEntryArgs(StubCache::kInterceptorArgsLength);
- __ PrepareCEntryFunction(ref);
-
- CEntryStub stub(1);
- __ CallStub(&stub);
+ __ CallExternalReference(
+ ExternalReference(IC_Utility(id), masm->isolate()),
+ StubCache::kInterceptorArgsLength);
}
@@ -1101,13 +1096,10 @@
// Save the name_ register across the call.
__ push(name_);
- PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder);
+ CompileCallLoadPropertyWithInterceptor(
+ masm, receiver, holder, name_, interceptor_holder,
+ IC::kLoadPropertyWithInterceptorForCall);
- __ CallExternalReference(
- ExternalReference(
- IC_Utility(IC::kLoadPropertyWithInterceptorForCall),
- masm->isolate()),
- StubCache::kInterceptorArgsLength);
// Restore the name_ register.
__ pop(name_);
// Leave the internal frame.
@@ -1123,11 +1115,9 @@
FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(holder, name_);
- CompileCallLoadPropertyWithInterceptor(masm,
- receiver,
- holder,
- name_,
- holder_obj);
+ CompileCallLoadPropertyWithInterceptor(
+ masm, receiver, holder, name_, holder_obj,
+ IC::kLoadPropertyWithInterceptorOnly);
__ pop(name_); // Restore the name.
__ pop(receiver); // Restore the holder.
}
@@ -1496,11 +1486,10 @@
// Invoke an interceptor. Note: map checks from receiver to
// interceptor's holder has been compiled before (see a caller
// of this method).
- CompileCallLoadPropertyWithInterceptor(masm(),
- receiver(),
- holder_reg,
- this->name(),
- interceptor_holder);
+ CompileCallLoadPropertyWithInterceptor(
+ masm(), receiver(), holder_reg, this->name(), interceptor_holder,
+ IC::kLoadPropertyWithInterceptorOnly);
+
// Check if interceptor provided a value for property. If it's
// the case, return immediately.
Label interceptor_failed;
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
index 9f1b939..512f532 100644
--- a/src/objects-printer.cc
+++ b/src/objects-printer.cc
@@ -862,8 +862,13 @@
shared()->name()->Print(out);
PrintF(out, "\n - context = ");
context()->ShortPrint(out);
- PrintF(out, "\n - literals = ");
- literals()->ShortPrint(out);
+ if (shared()->bound()) {
+ PrintF(out, "\n - bindings = ");
+ function_bindings()->ShortPrint(out);
+ } else {
+ PrintF(out, "\n - literals = ");
+ literals()->ShortPrint(out);
+ }
PrintF(out, "\n - code = ");
code()->ShortPrint(out);
PrintF(out, "\n");
diff --git a/src/objects.cc b/src/objects.cc
index 2283581..6e25e62 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -5656,14 +5656,6 @@
}
-Handle<JSObject> JSObject::Copy(Handle<JSObject> object,
- Handle<AllocationSite> site) {
- Isolate* isolate = object->GetIsolate();
- CALL_HEAP_FUNCTION(isolate,
- isolate->heap()->CopyJSObject(*object, *site), JSObject);
-}
-
-
Handle<JSObject> JSObject::Copy(Handle<JSObject> object) {
Isolate* isolate = object->GetIsolate();
CALL_HEAP_FUNCTION(isolate,
@@ -5671,258 +5663,233 @@
}
+template<class ContextObject>
class JSObjectWalkVisitor {
public:
- explicit JSObjectWalkVisitor(AllocationSiteContext* site_context) :
- site_context_(site_context) {}
- virtual ~JSObjectWalkVisitor() {}
+ JSObjectWalkVisitor(ContextObject* site_context, bool copying,
+ JSObject::DeepCopyHints hints)
+ : site_context_(site_context),
+ copying_(copying),
+ hints_(hints) {}
- Handle<JSObject> Visit(Handle<JSObject> object) {
- return StructureWalk(object);
- }
-
- virtual bool is_copying() = 0;
-
- protected:
Handle<JSObject> StructureWalk(Handle<JSObject> object);
- // The returned handle will be used for the object in all subsequent usages.
- // This allows VisitObject to make a copy of the object if desired.
- virtual Handle<JSObject> VisitObject(Handle<JSObject> object) = 0;
- virtual Handle<JSObject> VisitElementOrProperty(Handle<JSObject> object,
- Handle<JSObject> value) = 0;
-
- AllocationSiteContext* site_context() { return site_context_; }
-
- private:
- AllocationSiteContext* site_context_;
-};
-
-
-class JSObjectCopyVisitor: public JSObjectWalkVisitor {
- public:
- explicit JSObjectCopyVisitor(AllocationSiteContext* site_context)
- : JSObjectWalkVisitor(site_context) {}
-
- virtual bool is_copying() V8_OVERRIDE { return true; }
-
- // The returned handle will be used for the object in all
- // subsequent usages. This allows VisitObject to make a copy
- // of the object if desired.
- virtual Handle<JSObject> VisitObject(Handle<JSObject> object) V8_OVERRIDE {
- // Only create a memento if
- // 1) we have a JSArray, and
- // 2) the elements kind is palatable
- // 3) allow_mementos is true
- Handle<JSObject> copy;
- if (site_context()->activated() &&
- AllocationSite::CanTrack(object->map()->instance_type()) &&
- AllocationSite::GetMode(object->GetElementsKind()) ==
- TRACK_ALLOCATION_SITE) {
- copy = JSObject::Copy(object, site_context()->current());
- } else {
- copy = JSObject::Copy(object);
- }
-
- return copy;
- }
-
- virtual Handle<JSObject> VisitElementOrProperty(
- Handle<JSObject> object,
- Handle<JSObject> value) V8_OVERRIDE {
+ protected:
+ inline Handle<JSObject> VisitElementOrProperty(Handle<JSObject> object,
+ Handle<JSObject> value) {
Handle<AllocationSite> current_site = site_context()->EnterNewScope();
Handle<JSObject> copy_of_value = StructureWalk(value);
site_context()->ExitScope(current_site, value);
return copy_of_value;
}
+
+ inline ContextObject* site_context() { return site_context_; }
+ inline Isolate* isolate() { return site_context()->isolate(); }
+
+ inline bool copying() const { return copying_; }
+
+ private:
+ ContextObject* site_context_;
+ const bool copying_;
+ const JSObject::DeepCopyHints hints_;
};
-class JSObjectCreateAllocationSitesVisitor: public JSObjectWalkVisitor {
- public:
- explicit JSObjectCreateAllocationSitesVisitor(
- AllocationSiteContext* site_context)
- : JSObjectWalkVisitor(site_context) {}
+template <class ContextObject>
+Handle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
+ Handle<JSObject> object) {
+ Isolate* isolate = this->isolate();
+ bool copying = this->copying();
+ bool shallow = hints_ == JSObject::kObjectIsShallowArray;
- virtual bool is_copying() V8_OVERRIDE { return false; }
+ if (!shallow) {
+ StackLimitCheck check(isolate);
- // The returned handle will be used for the object in all
- // subsequent usages. This allows VisitObject to make a copy
- // of the object if desired.
- virtual Handle<JSObject> VisitObject(Handle<JSObject> object) V8_OVERRIDE {
- return object;
- }
-
- virtual Handle<JSObject> VisitElementOrProperty(
- Handle<JSObject> object,
- Handle<JSObject> value) V8_OVERRIDE {
- Handle<AllocationSite> current_site = site_context()->EnterNewScope();
- value = StructureWalk(value);
- site_context()->ExitScope(current_site, value);
- return value;
- }
-};
-
-
-Handle<JSObject> JSObjectWalkVisitor::StructureWalk(Handle<JSObject> object) {
- bool copying = is_copying();
- Isolate* isolate = object->GetIsolate();
- StackLimitCheck check(isolate);
- if (check.HasOverflowed()) {
- isolate->StackOverflow();
- return Handle<JSObject>::null();
+ if (check.HasOverflowed()) {
+ isolate->StackOverflow();
+ return Handle<JSObject>::null();
+ }
}
if (object->map()->is_deprecated()) {
JSObject::MigrateInstance(object);
}
- Handle<JSObject> copy = VisitObject(object);
+ Handle<JSObject> copy;
+ if (copying) {
+ Handle<AllocationSite> site_to_pass;
+ if (site_context()->activated() &&
+ AllocationSite::CanTrack(object->map()->instance_type()) &&
+ AllocationSite::GetMode(object->GetElementsKind()) ==
+ TRACK_ALLOCATION_SITE) {
+ site_to_pass = site_context()->current();
+ }
+ CALL_AND_RETRY_OR_DIE(isolate,
+ isolate->heap()->CopyJSObject(*object,
+ site_to_pass.is_null() ? NULL : *site_to_pass),
+ { copy = Handle<JSObject>(JSObject::cast(__object__),
+ isolate);
+ break;
+ },
+ return Handle<JSObject>());
+ } else {
+ copy = object;
+ }
+
ASSERT(copying || copy.is_identical_to(object));
- HandleScope scope(isolate);
-
- // Deep copy local properties.
- if (copy->HasFastProperties()) {
- Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors());
- int limit = copy->map()->NumberOfOwnDescriptors();
- for (int i = 0; i < limit; i++) {
- PropertyDetails details = descriptors->GetDetails(i);
- if (details.type() != FIELD) continue;
- int index = descriptors->GetFieldIndex(i);
- Handle<Object> value(object->RawFastPropertyAt(index), isolate);
- if (value->IsJSObject()) {
- value = VisitElementOrProperty(copy, Handle<JSObject>::cast(value));
- RETURN_IF_EMPTY_HANDLE_VALUE(isolate, value, Handle<JSObject>());
- } else {
- Representation representation = details.representation();
- value = NewStorageFor(isolate, value, representation);
- }
- if (copying) {
- copy->FastPropertyAtPut(index, *value);
- }
- }
- } else {
- Handle<FixedArray> names =
- isolate->factory()->NewFixedArray(copy->NumberOfLocalProperties());
- copy->GetLocalPropertyNames(*names, 0);
- for (int i = 0; i < names->length(); i++) {
- ASSERT(names->get(i)->IsString());
- Handle<String> key_string(String::cast(names->get(i)));
- PropertyAttributes attributes =
- copy->GetLocalPropertyAttribute(*key_string);
- // Only deep copy fields from the object literal expression.
- // In particular, don't try to copy the length attribute of
- // an array.
- if (attributes != NONE) continue;
- Handle<Object> value(
- copy->GetProperty(*key_string, &attributes)->ToObjectUnchecked(),
- isolate);
- if (value->IsJSObject()) {
- Handle<JSObject> result = VisitElementOrProperty(
- copy, Handle<JSObject>::cast(value));
- RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>());
- if (copying) {
- // Creating object copy for literals. No strict mode needed.
- CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetProperty(
- copy, key_string, result, NONE, kNonStrictMode));
- }
- }
- }
+ ElementsKind kind = copy->GetElementsKind();
+ if (copying && IsFastSmiOrObjectElementsKind(kind) &&
+ FixedArray::cast(copy->elements())->map() ==
+ isolate->heap()->fixed_cow_array_map()) {
+ isolate->counters()->cow_arrays_created_runtime()->Increment();
}
- // Deep copy local elements.
- // Pixel elements cannot be created using an object literal.
- ASSERT(!copy->HasExternalArrayElements());
- switch (copy->GetElementsKind()) {
- case FAST_SMI_ELEMENTS:
- case FAST_ELEMENTS:
- case FAST_HOLEY_SMI_ELEMENTS:
- case FAST_HOLEY_ELEMENTS: {
- Handle<FixedArray> elements(FixedArray::cast(copy->elements()));
- if (elements->map() == isolate->heap()->fixed_cow_array_map()) {
- if (copying) {
- isolate->counters()->cow_arrays_created_runtime()->Increment();
+ if (!shallow) {
+ HandleScope scope(isolate);
+
+ // Deep copy local properties.
+ if (copy->HasFastProperties()) {
+ Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors());
+ int limit = copy->map()->NumberOfOwnDescriptors();
+ for (int i = 0; i < limit; i++) {
+ PropertyDetails details = descriptors->GetDetails(i);
+ if (details.type() != FIELD) continue;
+ int index = descriptors->GetFieldIndex(i);
+ Handle<Object> value(object->RawFastPropertyAt(index), isolate);
+ if (value->IsJSObject()) {
+ value = VisitElementOrProperty(copy, Handle<JSObject>::cast(value));
+ RETURN_IF_EMPTY_HANDLE_VALUE(isolate, value, Handle<JSObject>());
+ } else {
+ Representation representation = details.representation();
+ value = NewStorageFor(isolate, value, representation);
}
+ if (copying) {
+ copy->FastPropertyAtPut(index, *value);
+ }
+ }
+ } else {
+ Handle<FixedArray> names =
+ isolate->factory()->NewFixedArray(copy->NumberOfLocalProperties());
+ copy->GetLocalPropertyNames(*names, 0);
+ for (int i = 0; i < names->length(); i++) {
+ ASSERT(names->get(i)->IsString());
+ Handle<String> key_string(String::cast(names->get(i)));
+ PropertyAttributes attributes =
+ copy->GetLocalPropertyAttribute(*key_string);
+ // Only deep copy fields from the object literal expression.
+ // In particular, don't try to copy the length attribute of
+ // an array.
+ if (attributes != NONE) continue;
+ Handle<Object> value(
+ copy->GetProperty(*key_string, &attributes)->ToObjectUnchecked(),
+ isolate);
+ if (value->IsJSObject()) {
+ Handle<JSObject> result = VisitElementOrProperty(
+ copy, Handle<JSObject>::cast(value));
+ RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>());
+ if (copying) {
+ // Creating object copy for literals. No strict mode needed.
+ CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetProperty(
+ copy, key_string, result, NONE, kNonStrictMode));
+ }
+ }
+ }
+ }
+
+ // Deep copy local elements.
+ // Pixel elements cannot be created using an object literal.
+ ASSERT(!copy->HasExternalArrayElements());
+ switch (kind) {
+ case FAST_SMI_ELEMENTS:
+ case FAST_ELEMENTS:
+ case FAST_HOLEY_SMI_ELEMENTS:
+ case FAST_HOLEY_ELEMENTS: {
+ Handle<FixedArray> elements(FixedArray::cast(copy->elements()));
+ if (elements->map() == isolate->heap()->fixed_cow_array_map()) {
#ifdef DEBUG
- for (int i = 0; i < elements->length(); i++) {
- ASSERT(!elements->get(i)->IsJSObject());
- }
+ for (int i = 0; i < elements->length(); i++) {
+ ASSERT(!elements->get(i)->IsJSObject());
+ }
#endif
- } else {
- for (int i = 0; i < elements->length(); i++) {
- Handle<Object> value(elements->get(i), isolate);
- ASSERT(value->IsSmi() ||
- value->IsTheHole() ||
- (IsFastObjectElementsKind(copy->GetElementsKind())));
- if (value->IsJSObject()) {
- Handle<JSObject> result = VisitElementOrProperty(
- copy, Handle<JSObject>::cast(value));
- RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>());
- if (copying) {
- elements->set(i, *result);
+ } else {
+ for (int i = 0; i < elements->length(); i++) {
+ Handle<Object> value(elements->get(i), isolate);
+ ASSERT(value->IsSmi() ||
+ value->IsTheHole() ||
+ (IsFastObjectElementsKind(copy->GetElementsKind())));
+ if (value->IsJSObject()) {
+ Handle<JSObject> result = VisitElementOrProperty(
+ copy, Handle<JSObject>::cast(value));
+ RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>());
+ if (copying) {
+ elements->set(i, *result);
+ }
}
}
}
+ break;
}
- break;
- }
- case DICTIONARY_ELEMENTS: {
- Handle<SeededNumberDictionary> element_dictionary(
- copy->element_dictionary());
- int capacity = element_dictionary->Capacity();
- for (int i = 0; i < capacity; i++) {
- Object* k = element_dictionary->KeyAt(i);
- if (element_dictionary->IsKey(k)) {
- Handle<Object> value(element_dictionary->ValueAt(i), isolate);
- if (value->IsJSObject()) {
- Handle<JSObject> result = VisitElementOrProperty(
- copy, Handle<JSObject>::cast(value));
- RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>());
- if (copying) {
- element_dictionary->ValueAtPut(i, *result);
+ case DICTIONARY_ELEMENTS: {
+ Handle<SeededNumberDictionary> element_dictionary(
+ copy->element_dictionary());
+ int capacity = element_dictionary->Capacity();
+ for (int i = 0; i < capacity; i++) {
+ Object* k = element_dictionary->KeyAt(i);
+ if (element_dictionary->IsKey(k)) {
+ Handle<Object> value(element_dictionary->ValueAt(i), isolate);
+ if (value->IsJSObject()) {
+ Handle<JSObject> result = VisitElementOrProperty(
+ copy, Handle<JSObject>::cast(value));
+ RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>());
+ if (copying) {
+ element_dictionary->ValueAtPut(i, *result);
+ }
}
}
}
+ break;
}
- break;
+ case NON_STRICT_ARGUMENTS_ELEMENTS:
+ UNIMPLEMENTED();
+ break;
+ case EXTERNAL_PIXEL_ELEMENTS:
+ case EXTERNAL_BYTE_ELEMENTS:
+ case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
+ case EXTERNAL_SHORT_ELEMENTS:
+ case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
+ case EXTERNAL_INT_ELEMENTS:
+ case EXTERNAL_UNSIGNED_INT_ELEMENTS:
+ case EXTERNAL_FLOAT_ELEMENTS:
+ case EXTERNAL_DOUBLE_ELEMENTS:
+ case FAST_DOUBLE_ELEMENTS:
+ case FAST_HOLEY_DOUBLE_ELEMENTS:
+ // No contained objects, nothing to do.
+ break;
}
- case NON_STRICT_ARGUMENTS_ELEMENTS:
- UNIMPLEMENTED();
- break;
- case EXTERNAL_PIXEL_ELEMENTS:
- case EXTERNAL_BYTE_ELEMENTS:
- case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
- case EXTERNAL_SHORT_ELEMENTS:
- case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
- case EXTERNAL_INT_ELEMENTS:
- case EXTERNAL_UNSIGNED_INT_ELEMENTS:
- case EXTERNAL_FLOAT_ELEMENTS:
- case EXTERNAL_DOUBLE_ELEMENTS:
- case FAST_DOUBLE_ELEMENTS:
- case FAST_HOLEY_DOUBLE_ELEMENTS:
- // No contained objects, nothing to do.
- break;
}
+
return copy;
}
-Handle<JSObject> JSObject::DeepWalk(Handle<JSObject> object,
- AllocationSiteContext* site_context) {
- JSObjectCreateAllocationSitesVisitor v(site_context);
- Handle<JSObject> result = v.Visit(object);
- ASSERT(!v.is_copying() &&
- (result.is_null() || result.is_identical_to(object)));
+Handle<JSObject> JSObject::DeepWalk(
+ Handle<JSObject> object,
+ AllocationSiteCreationContext* site_context) {
+ JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, false,
+ kNoHints);
+ Handle<JSObject> result = v.StructureWalk(object);
+ ASSERT(result.is_null() || result.is_identical_to(object));
return result;
}
Handle<JSObject> JSObject::DeepCopy(Handle<JSObject> object,
- AllocationSiteContext* site_context) {
- JSObjectCopyVisitor v(site_context);
- Handle<JSObject> copy = v.Visit(object);
- ASSERT(v.is_copying() && !copy.is_identical_to(object));
+ AllocationSiteUsageContext* site_context,
+ DeepCopyHints hints) {
+ JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, true, hints);
+ Handle<JSObject> copy = v.StructureWalk(object);
+ ASSERT(!copy.is_identical_to(object));
return copy;
}
diff --git a/src/objects.h b/src/objects.h
index 93d35bf..2ae1429 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -861,7 +861,8 @@
class AccessorPair;
class AllocationSite;
-class AllocationSiteContext;
+class AllocationSiteCreationContext;
+class AllocationSiteUsageContext;
class DictionaryElementsAccessor;
class ElementsAccessor;
class Failure;
@@ -2521,13 +2522,17 @@
static void SetObserved(Handle<JSObject> object);
// Copy object.
- static Handle<JSObject> Copy(Handle<JSObject> object,
- Handle<AllocationSite> site);
+ enum DeepCopyHints {
+ kNoHints = 0,
+ kObjectIsShallowArray = 1
+ };
+
static Handle<JSObject> Copy(Handle<JSObject> object);
static Handle<JSObject> DeepCopy(Handle<JSObject> object,
- AllocationSiteContext* site_context);
+ AllocationSiteUsageContext* site_context,
+ DeepCopyHints hints = kNoHints);
static Handle<JSObject> DeepWalk(Handle<JSObject> object,
- AllocationSiteContext* site_context);
+ AllocationSiteCreationContext* site_context);
// Casting.
static inline JSObject* cast(Object* obj);
diff --git a/src/property-details.h b/src/property-details.h
index 36f1406..617e9b2 100644
--- a/src/property-details.h
+++ b/src/property-details.h
@@ -131,6 +131,10 @@
}
bool is_more_general_than(const Representation& other) const {
+ if (kind_ == kExternal && other.kind_ == kNone) return true;
+ if (kind_ == kExternal && other.kind_ == kExternal) return false;
+ if (kind_ == kNone && other.kind_ == kExternal) return false;
+
ASSERT(kind_ != kExternal);
ASSERT(other.kind_ != kExternal);
if (IsHeapObject()) return other.IsDouble() || other.IsNone();
diff --git a/src/runtime.cc b/src/runtime.cc
index 092e91e..fbe4426 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -554,24 +554,52 @@
}
+static MaybeObject* CreateArrayLiteralImpl(Isolate* isolate,
+ Handle<FixedArray> literals,
+ int literals_index,
+ Handle<FixedArray> elements,
+ int flags) {
+ Handle<AllocationSite> site = GetLiteralAllocationSite(isolate, literals,
+ literals_index, elements);
+ RETURN_IF_EMPTY_HANDLE(isolate, site);
+
+ bool enable_mementos = (flags & ArrayLiteral::kDisableMementos) == 0;
+ Handle<JSObject> boilerplate(JSObject::cast(site->transition_info()));
+ AllocationSiteUsageContext usage_context(isolate, site, enable_mementos);
+ usage_context.EnterNewScope();
+ JSObject::DeepCopyHints hints = (flags & ArrayLiteral::kShallowElements) == 0
+ ? JSObject::kNoHints
+ : JSObject::kObjectIsShallowArray;
+ Handle<JSObject> copy = JSObject::DeepCopy(boilerplate, &usage_context,
+ hints);
+ usage_context.ExitScope(site, boilerplate);
+ RETURN_IF_EMPTY_HANDLE(isolate, copy);
+ return *copy;
+}
+
+
RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteral) {
HandleScope scope(isolate);
+ ASSERT(args.length() == 4);
+ CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
+ CONVERT_SMI_ARG_CHECKED(literals_index, 1);
+ CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
+ CONVERT_SMI_ARG_CHECKED(flags, 3);
+
+ return CreateArrayLiteralImpl(isolate, literals, literals_index, elements,
+ flags);
+}
+
+
+RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralStubBailout) {
+ HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
CONVERT_SMI_ARG_CHECKED(literals_index, 1);
CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
- Handle<AllocationSite> site = GetLiteralAllocationSite(isolate, literals,
- literals_index, elements);
- RETURN_IF_EMPTY_HANDLE(isolate, site);
-
- Handle<JSObject> boilerplate(JSObject::cast(site->transition_info()));
- AllocationSiteUsageContext usage_context(isolate, site, true);
- usage_context.EnterNewScope();
- Handle<JSObject> copy = JSObject::DeepCopy(boilerplate, &usage_context);
- usage_context.ExitScope(site, boilerplate);
- RETURN_IF_EMPTY_HANDLE(isolate, copy);
- return *copy;
+ return CreateArrayLiteralImpl(isolate, literals, literals_index, elements,
+ ArrayLiteral::kShallowElements);
}
@@ -835,20 +863,7 @@
}
-enum TypedArrayId {
- // arrayIds below should be synchromized with typedarray.js natives.
- ARRAY_ID_UINT8 = 1,
- ARRAY_ID_INT8 = 2,
- ARRAY_ID_UINT16 = 3,
- ARRAY_ID_INT16 = 4,
- ARRAY_ID_UINT32 = 5,
- ARRAY_ID_INT32 = 6,
- ARRAY_ID_FLOAT32 = 7,
- ARRAY_ID_FLOAT64 = 8,
- ARRAY_ID_UINT8C = 9
-};
-
-static void ArrayIdToTypeAndSize(
+void Runtime::ArrayIdToTypeAndSize(
int arrayId, ExternalArrayType* array_type, size_t* element_size) {
switch (arrayId) {
case ARRAY_ID_UINT8:
@@ -910,7 +925,7 @@
ExternalArrayType array_type = kExternalByteArray; // Bogus initialization.
size_t element_size = 1; // Bogus initialization.
- ArrayIdToTypeAndSize(arrayId, &array_type, &element_size);
+ Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &element_size);
holder->set_buffer(*buffer);
holder->set_byte_offset(*byte_offset_object);
@@ -962,7 +977,7 @@
ExternalArrayType array_type = kExternalByteArray; // Bogus initialization.
size_t element_size = 1; // Bogus initialization.
- ArrayIdToTypeAndSize(arrayId, &array_type, &element_size);
+ Runtime::ArrayIdToTypeAndSize(arrayId, &array_type, &element_size);
Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
size_t length = NumberToSize(isolate, *length_obj);
@@ -7686,16 +7701,6 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_ceil) {
- SealHandleScope shs(isolate);
- ASSERT(args.length() == 1);
- isolate->counters()->math_ceil()->Increment();
-
- CONVERT_DOUBLE_ARG_CHECKED(x, 0);
- return isolate->heap()->NumberFromDouble(ceiling(x));
-}
-
-
RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_cos) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
diff --git a/src/runtime.h b/src/runtime.h
index 43d4065..62c52a7 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -179,7 +179,6 @@
F(Math_asin, 1, 1) \
F(Math_atan, 1, 1) \
F(Math_atan2, 2, 1) \
- F(Math_ceil, 1, 1) \
F(Math_cos, 1, 1) \
F(Math_exp, 1, 1) \
F(Math_floor, 1, 1) \
@@ -300,7 +299,8 @@
/* Literals */ \
F(MaterializeRegExpLiteral, 4, 1)\
F(CreateObjectLiteral, 4, 1) \
- F(CreateArrayLiteral, 3, 1) \
+ F(CreateArrayLiteral, 4, 1) \
+ F(CreateArrayLiteralStubBailout, 3, 1) \
\
/* Harmony generators */ \
F(CreateJSGeneratorObject, 0, 1) \
@@ -829,6 +829,22 @@
Isolate* isolate,
JSArrayBuffer* phantom_array_buffer);
+ enum TypedArrayId {
+ // arrayIds below should be synchromized with typedarray.js natives.
+ ARRAY_ID_UINT8 = 1,
+ ARRAY_ID_INT8 = 2,
+ ARRAY_ID_UINT16 = 3,
+ ARRAY_ID_INT16 = 4,
+ ARRAY_ID_UINT32 = 5,
+ ARRAY_ID_INT32 = 6,
+ ARRAY_ID_FLOAT32 = 7,
+ ARRAY_ID_FLOAT64 = 8,
+ ARRAY_ID_UINT8C = 9
+ };
+
+ static void ArrayIdToTypeAndSize(int array_id,
+ ExternalArrayType *type, size_t *element_size);
+
// Helper functions used stubs.
static void PerformGC(Object* result, Isolate* isolate);
diff --git a/src/typedarray.js b/src/typedarray.js
index fc3a608..ed9de23 100644
--- a/src/typedarray.js
+++ b/src/typedarray.js
@@ -78,7 +78,8 @@
var newLength = ToPositiveInteger(length, "invalid_typed_array_length");
newByteLength = newLength * ELEMENT_SIZE;
}
- if (offset + newByteLength > bufferByteLength) {
+ if ((offset + newByteLength > bufferByteLength)
+ || (newLength > %MaxSmi())) {
throw MakeRangeError("invalid_typed_array_length");
}
%TypedArrayInitialize(obj, ARRAY_ID, buffer, offset, newByteLength);
diff --git a/src/v8-counters.h b/src/v8-counters.h
index 54e8100..9178046 100644
--- a/src/v8-counters.h
+++ b/src/v8-counters.h
@@ -242,7 +242,6 @@
SC(math_asin, V8.MathAsin) \
SC(math_atan, V8.MathAtan) \
SC(math_atan2, V8.MathAtan2) \
- SC(math_ceil, V8.MathCeil) \
SC(math_cos, V8.MathCos) \
SC(math_exp, V8.MathExp) \
SC(math_floor, V8.MathFloor) \
diff --git a/src/version.cc b/src/version.cc
index ce766ce..e03ed8d 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
// system so their names cannot be changed without changing the scripts.
#define MAJOR_VERSION 3
#define MINOR_VERSION 23
-#define BUILD_NUMBER 11
+#define BUILD_NUMBER 12
#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h
index ac69a24..709b61b 100644
--- a/src/x64/assembler-x64.h
+++ b/src/x64/assembler-x64.h
@@ -586,13 +586,6 @@
set_target_address_at(instruction_payload, target);
}
- // This sets the branch destination (which is a load instruction on x64).
- // This is for calls and branches to runtime code.
- inline static void set_external_target_at(Address instruction_payload,
- Address target) {
- *reinterpret_cast<Address*>(instruction_payload) = target;
- }
-
inline Handle<Object> code_target_object_handle_at(Address pc);
inline Address runtime_entry_at(Address pc);
// Number of bytes taken up by the branch target in the code.
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index 8712e27..4fb3a70 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -78,7 +78,7 @@
descriptor->register_param_count_ = 3;
descriptor->register_params_ = registers;
descriptor->deoptimization_handler_ =
- Runtime::FunctionForId(Runtime::kCreateArrayLiteral)->entry;
+ Runtime::FunctionForId(Runtime::kCreateArrayLiteralStubBailout)->entry;
}
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index a62fde0..ed4c3ad 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -1726,6 +1726,10 @@
Comment cmnt(masm_, "[ ArrayLiteral");
expr->BuildConstantElements(isolate());
+ int flags = expr->depth() == 1
+ ? ArrayLiteral::kShallowElements
+ : ArrayLiteral::kNoFlags;
+
ZoneList<Expression*>* subexprs = expr->values();
int length = subexprs->length();
Handle<FixedArray> constant_elements = expr->constant_elements();
@@ -1758,7 +1762,8 @@
__ push(FieldOperand(rbx, JSFunction::kLiteralsOffset));
__ Push(Smi::FromInt(expr->literal_index()));
__ Push(constant_elements);
- __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
+ __ Push(Smi::FromInt(flags));
+ __ CallRuntime(Runtime::kCreateArrayLiteral, 4);
} else {
ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) ||
FLAG_smi_only_arrays);
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index cf0632e..e56bb54 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -1781,14 +1781,22 @@
LOperand* left = instr->left();
LOperand* right = instr->right();
+ Representation target_rep = instr->hydrogen()->representation();
+ bool is_q = target_rep.IsSmi() || target_rep.IsExternal();
+
if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) {
if (right->IsConstantOperand()) {
int32_t offset = ToInteger32(LConstantOperand::cast(right));
- __ leal(ToRegister(instr->result()),
- MemOperand(ToRegister(left), offset));
+ if (is_q) {
+ __ lea(ToRegister(instr->result()),
+ MemOperand(ToRegister(left), offset));
+ } else {
+ __ leal(ToRegister(instr->result()),
+ MemOperand(ToRegister(left), offset));
+ }
} else {
Operand address(ToRegister(left), ToRegister(right), times_1, 0);
- if (instr->hydrogen()->representation().IsSmi()) {
+ if (is_q) {
__ lea(ToRegister(instr->result()), address);
} else {
__ leal(ToRegister(instr->result()), address);
@@ -1796,16 +1804,21 @@
}
} else {
if (right->IsConstantOperand()) {
- __ addl(ToRegister(left),
- Immediate(ToInteger32(LConstantOperand::cast(right))));
+ if (is_q) {
+ __ addq(ToRegister(left),
+ Immediate(ToInteger32(LConstantOperand::cast(right))));
+ } else {
+ __ addl(ToRegister(left),
+ Immediate(ToInteger32(LConstantOperand::cast(right))));
+ }
} else if (right->IsRegister()) {
- if (instr->hydrogen_value()->representation().IsSmi()) {
+ if (is_q) {
__ addq(ToRegister(left), ToRegister(right));
} else {
__ addl(ToRegister(left), ToRegister(right));
}
} else {
- if (instr->hydrogen_value()->representation().IsSmi()) {
+ if (is_q) {
__ addq(ToRegister(left), ToOperand(right));
} else {
__ addl(ToRegister(left), ToOperand(right));
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index fa1bdaa..78bc5bb 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -1557,6 +1557,21 @@
result = AssignEnvironment(result);
}
return result;
+ } else if (instr->representation().IsExternal()) {
+ ASSERT(instr->left()->representation().IsExternal());
+ ASSERT(instr->right()->representation().IsInteger32());
+ ASSERT(!instr->CheckFlag(HValue::kCanOverflow));
+ bool use_lea = LAddI::UseLea(instr);
+ LOperand* left = UseRegisterAtStart(instr->left());
+ HValue* right_candidate = instr->right();
+ LOperand* right = use_lea
+ ? UseRegisterOrConstantAtStart(right_candidate)
+ : UseOrConstantAtStart(right_candidate);
+ LAddI* add = new(zone()) LAddI(left, right);
+ LInstruction* result = use_lea
+ ? DefineAsRegister(add)
+ : DefineSameAsFirst(add);
+ return result;
} else if (instr->representation().IsDouble()) {
return DoArithmeticD(Token::ADD, instr);
} else {
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index 57c6a35..e64698c 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -379,17 +379,12 @@
Register receiver,
Register holder,
Register name,
- Handle<JSObject> holder_obj) {
+ Handle<JSObject> holder_obj,
+ IC::UtilityId id) {
PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
-
- ExternalReference ref =
- ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly),
- masm->isolate());
- __ Set(rax, StubCache::kInterceptorArgsLength);
- __ LoadAddress(rbx, ref);
-
- CEntryStub stub(1);
- __ CallStub(&stub);
+ __ CallExternalReference(
+ ExternalReference(IC_Utility(id), masm->isolate()),
+ StubCache::kInterceptorArgsLength);
}
@@ -794,12 +789,9 @@
// Save the name_ register across the call.
__ push(name_);
- PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder);
-
- __ CallExternalReference(
- ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall),
- masm->isolate()),
- StubCache::kInterceptorArgsLength);
+ CompileCallLoadPropertyWithInterceptor(
+ masm, receiver, holder, name_, interceptor_holder,
+ IC::kLoadPropertyWithInterceptorForCall);
// Restore the name_ register.
__ pop(name_);
@@ -817,11 +809,9 @@
__ push(holder); // Save the holder.
__ push(name_); // Save the name.
- CompileCallLoadPropertyWithInterceptor(masm,
- receiver,
- holder,
- name_,
- holder_obj);
+ CompileCallLoadPropertyWithInterceptor(
+ masm, receiver, holder, name_, holder_obj,
+ IC::kLoadPropertyWithInterceptorOnly);
__ pop(name_); // Restore the name.
__ pop(receiver); // Restore the holder.
@@ -1501,11 +1491,9 @@
// Invoke an interceptor. Note: map checks from receiver to
// interceptor's holder has been compiled before (see a caller
// of this method.)
- CompileCallLoadPropertyWithInterceptor(masm(),
- receiver(),
- holder_reg,
- this->name(),
- interceptor_holder);
+ CompileCallLoadPropertyWithInterceptor(
+ masm(), receiver(), holder_reg, this->name(), interceptor_holder,
+ IC::kLoadPropertyWithInterceptorOnly);
// Check if interceptor provided a value for property. If it's
// the case, return immediately.