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/ChangeLog b/ChangeLog
index fa508c8..aee6b50 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2013-11-26: Version 3.23.12
+
+ Performance and stability improvements on all platforms.
+
+
2013-11-25: Version 3.23.11
Deprecate old versions of Isolate::SetData and GetData.
diff --git a/include/v8.h b/include/v8.h
index 6e1ac3f..a15edf2 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -1137,6 +1137,8 @@
bool IsSharedCrossOrigin() const;
// TODO(1245381): Print to a string instead of on a FILE.
+ static void PrintCurrentStackTrace(Isolate* isolate, FILE* out);
+ // Will be deprecated soon.
static void PrintCurrentStackTrace(FILE* out);
static const int kNoLineNumberInfo = 0;
@@ -1192,6 +1194,11 @@
* StackFrame.
*/
static Local<StackTrace> CurrentStackTrace(
+ Isolate* isolate,
+ int frame_limit,
+ StackTraceOptions options = kOverview);
+ // Will be deprecated soon.
+ static Local<StackTrace> CurrentStackTrace(
int frame_limit,
StackTraceOptions options = kOverview);
};
@@ -1524,6 +1531,8 @@
class V8_EXPORT Boolean : public Primitive {
public:
bool Value() const;
+ V8_INLINE static Handle<Boolean> New(Isolate* isolate, bool value);
+ // Will be deprecated soon.
V8_INLINE static Handle<Boolean> New(bool value);
};
@@ -1792,6 +1801,9 @@
* should the underlying buffer be deallocated or modified except through the
* destructor of the external string resource.
*/
+ static Local<String> NewExternal(Isolate* isolate,
+ ExternalStringResource* resource);
+ // Will be deprecated soon.
static Local<String> NewExternal(ExternalStringResource* resource);
/**
@@ -1813,6 +1825,9 @@
* should the underlying buffer be deallocated or modified except through the
* destructor of the external string resource.
*/
+ static Local<String> NewExternal(Isolate* isolate,
+ ExternalAsciiStringResource* resource);
+ // Will be deprecated soon.
static Local<String> NewExternal(ExternalAsciiStringResource* resource);
/**
@@ -1966,8 +1981,9 @@
class V8_EXPORT Number : public Primitive {
public:
double Value() const;
- static Local<Number> New(double value);
static Local<Number> New(Isolate* isolate, double value);
+ // Will be deprecated soon.
+ static Local<Number> New(double value);
V8_INLINE static Number* Cast(v8::Value* obj);
private:
Number();
@@ -1980,10 +1996,13 @@
*/
class V8_EXPORT Integer : public Number {
public:
- static Local<Integer> New(int32_t value);
- static Local<Integer> NewFromUnsigned(uint32_t value);
+ static Local<Integer> New(Isolate* isolate, int32_t value);
+ static Local<Integer> NewFromUnsigned(Isolate* isolate, uint32_t value);
+ // Will be deprecated soon.
static Local<Integer> New(int32_t value, Isolate*);
static Local<Integer> NewFromUnsigned(uint32_t value, Isolate*);
+ static Local<Integer> New(int32_t value);
+ static Local<Integer> NewFromUnsigned(uint32_t value);
int64_t Value() const;
V8_INLINE static Integer* Cast(v8::Value* obj);
private:
@@ -2336,6 +2355,8 @@
*/
Local<Value> CallAsConstructor(int argc, Handle<Value> argv[]);
+ static Local<Object> New(Isolate* isolate);
+ // Will be deprecated soon.
static Local<Object> New();
V8_INLINE static Object* Cast(Value* obj);
@@ -2364,6 +2385,8 @@
* Creates a JavaScript array with the given length. If the length
* is negative the returned array will have length 0.
*/
+ static Local<Array> New(Isolate* isolate, int length = 0);
+ // Will be deprecated soon.
static Local<Array> New(int length = 0);
V8_INLINE static Array* Cast(Value* obj);
@@ -2627,6 +2650,8 @@
* will be deallocated when it is garbage-collected,
* unless the object is externalized.
*/
+ static Local<ArrayBuffer> New(Isolate* isolate, size_t byte_length);
+ // Will be deprecated soon.
static Local<ArrayBuffer> New(size_t byte_length);
/**
@@ -2635,6 +2660,9 @@
* The memory block will not be reclaimed when a created ArrayBuffer
* is garbage-collected.
*/
+ static Local<ArrayBuffer> New(Isolate* isolate, void* data,
+ size_t byte_length);
+ // Will be deprecated soon.
static Local<ArrayBuffer> New(void* data, size_t byte_length);
/**
@@ -2895,6 +2923,8 @@
*/
class V8_EXPORT Date : public Object {
public:
+ static Local<Value> New(Isolate* isolate, double time);
+ // Will be deprecated soon.
static Local<Value> New(double time);
V8_DEPRECATED(
@@ -2921,6 +2951,8 @@
* This API should not be called more than needed as it will
* negatively impact the performance of date operations.
*/
+ static void DateTimeConfigurationChangeNotification(Isolate* isolate);
+ // Will be deprecated soon.
static void DateTimeConfigurationChangeNotification();
private:
@@ -2933,6 +2965,8 @@
*/
class V8_EXPORT NumberObject : public Object {
public:
+ static Local<Value> New(Isolate* isolate, double value);
+ // Will be deprecated soon.
static Local<Value> New(double value);
V8_DEPRECATED(
@@ -3094,6 +3128,8 @@
/** Adds a property to each instance created by this template.*/
void Set(Handle<String> name, Handle<Data> value,
PropertyAttribute attributes = None);
+ V8_INLINE void Set(Isolate* isolate, const char* name, Handle<Data> value);
+ // Will be deprecated soon.
V8_INLINE void Set(const char* name, Handle<Data> value);
void SetAccessorProperty(
@@ -3377,6 +3413,13 @@
public:
/** Creates a function template.*/
static Local<FunctionTemplate> New(
+ Isolate* isolate,
+ FunctionCallback callback = 0,
+ Handle<Value> data = Handle<Value>(),
+ Handle<Signature> signature = Handle<Signature>(),
+ int length = 0);
+ // Will be deprecated soon.
+ static Local<FunctionTemplate> New(
FunctionCallback callback = 0,
Handle<Value> data = Handle<Value>(),
Handle<Signature> signature = Handle<Signature>(),
@@ -3463,6 +3506,8 @@
class V8_EXPORT ObjectTemplate : public Template {
public:
/** Creates an ObjectTemplate. */
+ static Local<ObjectTemplate> New(Isolate* isolate);
+ // Will be deprecated soon.
static Local<ObjectTemplate> New();
/** Creates a new instance of this template.*/
@@ -3604,7 +3649,8 @@
private:
ObjectTemplate();
- static Local<ObjectTemplate> New(Handle<FunctionTemplate> constructor);
+ static Local<ObjectTemplate> New(internal::Isolate* isolate,
+ Handle<FunctionTemplate> constructor);
friend class FunctionTemplate;
};
@@ -3615,6 +3661,12 @@
*/
class V8_EXPORT Signature : public Data {
public:
+ static Local<Signature> New(Isolate* isolate,
+ Handle<FunctionTemplate> receiver =
+ Handle<FunctionTemplate>(),
+ int argc = 0,
+ Handle<FunctionTemplate> argv[] = 0);
+ // Will be deprecated soon.
static Local<Signature> New(Handle<FunctionTemplate> receiver =
Handle<FunctionTemplate>(),
int argc = 0,
@@ -3630,8 +3682,13 @@
*/
class V8_EXPORT AccessorSignature : public Data {
public:
+ static Local<AccessorSignature> New(Isolate* isolate,
+ Handle<FunctionTemplate> receiver =
+ Handle<FunctionTemplate>());
+ // Will be deprecated soon.
static Local<AccessorSignature> New(Handle<FunctionTemplate> receiver =
Handle<FunctionTemplate>());
+
private:
AccessorSignature();
};
@@ -3735,6 +3792,11 @@
const char** deps = 0,
int source_length = -1);
virtual ~Extension() { }
+ virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
+ v8::Isolate* isolate, v8::Handle<v8::String> name) {
+ return GetNativeFunction(name);
+ }
+ // Will be deprecated soon.
virtual v8::Handle<v8::FunctionTemplate>
GetNativeFunction(v8::Handle<v8::String> name) {
return v8::Handle<v8::FunctionTemplate>();
@@ -3779,17 +3841,17 @@
// --- Statics ---
-
-Handle<Primitive> V8_EXPORT Undefined();
-Handle<Primitive> V8_EXPORT Null();
-Handle<Boolean> V8_EXPORT True();
-Handle<Boolean> V8_EXPORT False();
-
V8_INLINE Handle<Primitive> Undefined(Isolate* isolate);
V8_INLINE Handle<Primitive> Null(Isolate* isolate);
V8_INLINE Handle<Boolean> True(Isolate* isolate);
V8_INLINE Handle<Boolean> False(Isolate* isolate);
+// Will be removed soon.
+Handle<Primitive> V8_EXPORT Undefined();
+Handle<Primitive> V8_EXPORT Null();
+Handle<Boolean> V8_EXPORT True();
+Handle<Boolean> V8_EXPORT False();
+
/**
* A set of constraints that specifies the limits of the runtime's memory use.
@@ -6031,14 +6093,23 @@
}
-Handle<Boolean> Boolean::New(bool value) {
- Isolate* isolate = Isolate::GetCurrent();
+Handle<Boolean> Boolean::New(Isolate* isolate, bool value) {
return value ? True(isolate) : False(isolate);
}
+Handle<Boolean> Boolean::New(bool value) {
+ return Boolean::New(Isolate::GetCurrent(), value);
+}
+
+
+void Template::Set(Isolate* isolate, const char* name, v8::Handle<Data> value) {
+ Set(v8::String::NewFromUtf8(isolate, name), value);
+}
+
+
void Template::Set(const char* name, v8::Handle<Data> value) {
- Set(v8::String::NewFromUtf8(Isolate::GetCurrent(), name), value);
+ Set(Isolate::GetCurrent(), name, value);
}
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.
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 0db63c1..23756db 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -1631,7 +1631,7 @@
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
- Local<Value> primitive_false = Boolean::New(false);
+ Local<Value> primitive_false = Boolean::New(env->GetIsolate(), false);
CHECK(primitive_false->IsBoolean());
CHECK(!primitive_false->IsBooleanObject());
CHECK(!primitive_false->BooleanValue());
@@ -1654,7 +1654,7 @@
CHECK(!false_boolean_object->IsTrue());
CHECK(!false_boolean_object->IsFalse());
- Local<Value> primitive_true = Boolean::New(true);
+ Local<Value> primitive_true = Boolean::New(env->GetIsolate(), true);
CHECK(primitive_true->IsBoolean());
CHECK(!primitive_true->IsBooleanObject());
CHECK(primitive_true->BooleanValue());
@@ -2625,7 +2625,7 @@
CheckEmbedderData(&env, 2, v8::String::NewFromUtf8(env->GetIsolate(),
"over the lazy dog."));
CheckEmbedderData(&env, 1, v8::Number::New(1.2345));
- CheckEmbedderData(&env, 0, v8::Boolean::New(true));
+ CheckEmbedderData(&env, 0, v8::Boolean::New(env->GetIsolate(), true));
}
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index eb9789a..00e4020 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -7514,9 +7514,9 @@
for (int i = 0; loop_bodies[i] != NULL; i++) {
// Perform a lazy deoptimization after various numbers of breaks
// have been hit.
- for (int j = 0; j < 11; j++) {
+ for (int j = 0; j < 7; j++) {
break_point_hit_count_deoptimize = j;
- if (j == 10) {
+ if (j == 6) {
break_point_hit_count_deoptimize = kBreaksPerTest;
}
diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc
index 86ed230..458493b 100644
--- a/test/cctest/test-heap-profiler.cc
+++ b/test/cctest/test-heap-profiler.cc
@@ -1936,8 +1936,8 @@
CHECK_EQ(v8::internal::Context::MIN_CONTEXT_SLOTS + num_objects - 1,
context_object->GetChildrenCount());
// Check all the objects have got their names.
- // ... well check just every 8th because otherwise it's too slow in debug.
- for (int i = 0; i < num_objects - 1; i += 8) {
+ // ... well check just every 15th because otherwise it's too slow in debug.
+ for (int i = 0; i < num_objects - 1; i += 15) {
i::EmbeddedVector<char, 100> var_name;
i::OS::SNPrintF(var_name, "f_%d", i);
const v8::HeapGraphNode* f_object = GetProperty(
diff --git a/test/cctest/test-representation.cc b/test/cctest/test-representation.cc
index 15321f3..95a65cb 100644
--- a/test/cctest/test-representation.cc
+++ b/test/cctest/test-representation.cc
@@ -121,4 +121,8 @@
TestPairNegative(Representation::HeapObject(), Representation::Integer32());
TestPairPositive(Representation::Double(), Representation::Integer32());
TestPairPositive(Representation::Tagged(), Representation::Integer32());
+
+ TestPairNegative(Representation::None(), Representation::External());
+ TestPairNegative(Representation::External(), Representation::External());
+ TestPairPositive(Representation::External(), Representation::None());
}
diff --git a/test/mjsunit/array-literal-feedback.js b/test/mjsunit/array-literal-feedback.js
index 93ed3bc..3e95eab 100644
--- a/test/mjsunit/array-literal-feedback.js
+++ b/test/mjsunit/array-literal-feedback.js
@@ -93,11 +93,15 @@
}
get_literal(3);
- get_literal(3);
- %OptimizeFunctionOnNextCall(get_literal);
+ // It's important to store a from before we crankshaft get_literal, because
+ // mementos won't be created from crankshafted code at all.
a = get_literal(3);
+ %OptimizeFunctionOnNextCall(get_literal);
+ get_literal(3);
assertOptimized(get_literal);
assertTrue(%HasFastSmiElements(a));
+ // a has a memento so the transition caused by the store will affect the
+ // boilerplate.
a[0] = 3.5;
// We should have transitioned the boilerplate array to double, and
diff --git a/test/mjsunit/compiler/math-floor-global.js b/test/mjsunit/compiler/math-floor-global.js
index 9ec183f..3b9d125 100644
--- a/test/mjsunit/compiler/math-floor-global.js
+++ b/test/mjsunit/compiler/math-floor-global.js
@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --max-new-space-size=256 --allow-natives-syntax
+// Flags: --max-new-space-size=128 --allow-natives-syntax
// Test inlining of Math.floor when assigned to a global.
var flo = Math.floor;
@@ -140,8 +140,9 @@
// Test in a loop to cover the custom IC and GC-related issues.
-for (var i = 0; i < 50; i++) {
+for (var i = 0; i < 10; i++) {
test();
+ new Array(i * 10000);
}
@@ -158,4 +159,4 @@
%OptimizeFunctionOnNextCall(floorsum);
// The optimized function will deopt. Run it with enough iterations to try
// to optimize via OSR (triggering the bug).
-assertEquals(-0, floorsum(100000, -0));
+assertEquals(-0, floorsum(50000, -0));
diff --git a/test/mjsunit/compiler/math-floor-local.js b/test/mjsunit/compiler/math-floor-local.js
index e44b15c..fef3347 100644
--- a/test/mjsunit/compiler/math-floor-local.js
+++ b/test/mjsunit/compiler/math-floor-local.js
@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --max-new-space-size=256 --allow-natives-syntax
+// Flags: --max-new-space-size=128 --allow-natives-syntax
// Test inlining of Math.floor when assigned to a local.
var test_id = 0;
@@ -140,8 +140,9 @@
// Test in a loop to cover the custom IC and GC-related issues.
-for (var i = 0; i < 50; i++) {
+for (var i = 0; i < 10; i++) {
test();
+ new Array(i * 10000);
}
diff --git a/test/mjsunit/compiler/osr-with-args.js b/test/mjsunit/compiler/osr-with-args.js
index 44fa1cb..4817ad7 100644
--- a/test/mjsunit/compiler/osr-with-args.js
+++ b/test/mjsunit/compiler/osr-with-args.js
@@ -29,7 +29,7 @@
function f() {
var sum = 0;
- for (var i = 0; i < 1000000; i++) {
+ for (var i = 0; i < 100000; i++) {
var t = arguments[0] + 2;
var x = arguments[1] + 2;
var y = t + x + 5;
@@ -39,6 +39,6 @@
return sum;
}
-for (var i = 0; i < 4; i++) {
- assertEquals(17000000, f(2, 3));
+for (var i = 0; i < 3; i++) {
+ assertEquals(1700000, f(2, 3));
}
diff --git a/test/mjsunit/compiler/regress-4.js b/test/mjsunit/compiler/regress-4.js
index 0ec9a12..9a212ba 100644
--- a/test/mjsunit/compiler/regress-4.js
+++ b/test/mjsunit/compiler/regress-4.js
@@ -34,7 +34,7 @@
return y+x;
}
-for (var i=0; i<10000000; i++) f(42);
+for (var i=0; i<100000; i++) f(42);
var result = f("foo");
assertEquals("0foo6", result);
diff --git a/test/mjsunit/debug-step-4-in-frame.js b/test/mjsunit/debug-step-4-in-frame.js
index 65ac490..9388430 100644
--- a/test/mjsunit/debug-step-4-in-frame.js
+++ b/test/mjsunit/debug-step-4-in-frame.js
@@ -37,18 +37,18 @@
function f() {
var a = 1978;
- for (state[2] = 0; state[2] < 5; state[2]++) {
+ for (state[2] = 0; state[2] < 3; state[2]++) {
void String(a);
}
}
function g() {
- for (state[1] = 0; state[1] < 5; state[1]++) {
+ for (state[1] = 0; state[1] < 3; state[1]++) {
f();
}
}
function h() {
state = [-1, -1, -1];
- for (state[0] = 0; state[0] < 5; state[0]++) {
+ for (state[0] = 0; state[0] < 3; state[0]++) {
g();
}
}
@@ -123,10 +123,10 @@
TestCase(0, 8, "0,0,3");
// Stepping in the frame #1.
-TestCase(1, 0, "0,0,5");
-TestCase(1, 3, "0,1,5");
-TestCase(1, 8, "0,4,5");
+TestCase(1, 0, "0,0,3");
+TestCase(1, 3, "0,1,3");
+TestCase(1, 7, "0,3,3");
// Stepping in the frame #2.
-TestCase(2, 3, "1,5,5");
-TestCase(2, 8, "4,5,5");
+TestCase(2, 3, "1,3,3");
+TestCase(2, 7, "3,3,3");
diff --git a/test/mjsunit/fuzz-natives-part1.js b/test/mjsunit/fuzz-natives-part1.js
index c30069e..88d505a 100644
--- a/test/mjsunit/fuzz-natives-part1.js
+++ b/test/mjsunit/fuzz-natives-part1.js
@@ -204,6 +204,9 @@
"_OneByteSeqStringSetChar": true,
"_TwoByteSeqStringSetChar": true,
+ // Only applicable to TypedArrays.
+ "TypedArrayInitialize": true,
+
// Only applicable to generators.
"_GeneratorNext": true,
"_GeneratorThrow": true,
diff --git a/test/mjsunit/fuzz-natives-part2.js b/test/mjsunit/fuzz-natives-part2.js
index e73f3bd..e86a05d 100644
--- a/test/mjsunit/fuzz-natives-part2.js
+++ b/test/mjsunit/fuzz-natives-part2.js
@@ -205,6 +205,9 @@
"_OneByteSeqStringSetChar": true,
"_TwoByteSeqStringSetChar": true,
+ // Only applicable to TypedArrays.
+ "TypedArrayInitialize": true,
+
// Only applicable to generators.
"_GeneratorNext": true,
"_GeneratorThrow": true,
diff --git a/test/mjsunit/fuzz-natives-part3.js b/test/mjsunit/fuzz-natives-part3.js
index 6a73498..0d5ec6f 100644
--- a/test/mjsunit/fuzz-natives-part3.js
+++ b/test/mjsunit/fuzz-natives-part3.js
@@ -204,6 +204,9 @@
"_OneByteSeqStringSetChar": true,
"_TwoByteSeqStringSetChar": true,
+ // Only applicable to TypedArrays.
+ "TypedArrayInitialize": true,
+
// Only applicable to generators.
"_GeneratorNext": true,
"_GeneratorThrow": true,
diff --git a/test/mjsunit/fuzz-natives-part4.js b/test/mjsunit/fuzz-natives-part4.js
index edeaa87..a17a840 100644
--- a/test/mjsunit/fuzz-natives-part4.js
+++ b/test/mjsunit/fuzz-natives-part4.js
@@ -204,6 +204,9 @@
"_OneByteSeqStringSetChar": true,
"_TwoByteSeqStringSetChar": true,
+ // Only applicable to TypedArrays.
+ "TypedArrayInitialize": true,
+
// Only applicable to generators.
"_GeneratorNext": true,
"_GeneratorThrow": true,
diff --git a/test/mjsunit/harmony/private.js b/test/mjsunit/harmony/private.js
index 884e31b..09cf7f7 100644
--- a/test/mjsunit/harmony/private.js
+++ b/test/mjsunit/harmony/private.js
@@ -317,7 +317,7 @@
var a = {};
a[key] = "abc";
- for (var i = 0; i < 1000000; i++) {
+ for (var i = 0; i < 100000; i++) {
a[key] += "a"; // Allocations cause a scavenge.
}
}
diff --git a/test/mjsunit/harmony/symbols.js b/test/mjsunit/harmony/symbols.js
index 1fc3945..3fcd06d 100644
--- a/test/mjsunit/harmony/symbols.js
+++ b/test/mjsunit/harmony/symbols.js
@@ -345,7 +345,7 @@
var a = {};
a[key] = "abc";
- for (var i = 0; i < 1000000; i++) {
+ for (var i = 0; i < 100000; i++) {
a[key] += "a"; // Allocations cause a scavenge.
}
}
diff --git a/test/mjsunit/json2.js b/test/mjsunit/json2.js
index cf20b90..0894d77 100644
--- a/test/mjsunit/json2.js
+++ b/test/mjsunit/json2.js
@@ -40,12 +40,13 @@
var array_1 = [];
var array_2 = [];
-array_1[100000] = 1;
-array_2[100000] = function() { return 1; };
-var nulls = "";
-for (var i = 0; i < 100000; i++) {
- nulls += 'null,';
+array_1[1<<17] = 1;
+array_2[1<<17] = function() { return 1; };
+var nulls = "null,";
+for (var i = 0; i < 17; i++) {
+ nulls += nulls;
}
+
expected_1 = '[' + nulls + '1]';
expected_2 = '[' + nulls + 'null]';
TestStringify(expected_1, array_1);
diff --git a/test/mjsunit/limit-locals.js b/test/mjsunit/limit-locals.js
index a166f30..1d36c80 100644
--- a/test/mjsunit/limit-locals.js
+++ b/test/mjsunit/limit-locals.js
@@ -34,9 +34,9 @@
test_suffix = " suffix";
var src = "test_prefix + (function () {"
for (var i = 1; i <= n; i++) {
- src += "var x" + i + ";";
+ src += "; var x" + i;
}
- src += "return " + n + ";})() + test_suffix";
+ src += "; return " + n + ";})() + test_suffix";
return eval(src);
}
diff --git a/test/mjsunit/math-floor-part1.js b/test/mjsunit/math-floor-part1.js
index 313f272..dd4deb0 100644
--- a/test/mjsunit/math-floor-part1.js
+++ b/test/mjsunit/math-floor-part1.js
@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --max-new-space-size=256 --allow-natives-syntax
+// Flags: --max-new-space-size=128 --allow-natives-syntax
var test_id = 0;
@@ -83,6 +83,7 @@
// Test in a loop to cover the custom IC and GC-related issues.
-for (var i = 0; i < 100; i++) {
+for (var i = 0; i < 10; i++) {
test();
+ new Array(i * 10000);
}
diff --git a/test/mjsunit/regress/regress-2318.js b/test/mjsunit/regress/regress-2318.js
index ca67ab2..5fa8a4f 100644
--- a/test/mjsunit/regress/regress-2318.js
+++ b/test/mjsunit/regress/regress-2318.js
@@ -25,7 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// Flags: --expose-debug-as debug --nostack-trace-on-abort
+// Flags: --expose-debug-as debug --nostack-trace-on-abort --stack-size=100
function f() {
var i = 0;
diff --git a/test/mjsunit/regress/regress-2790.js b/test/mjsunit/regress/regress-2790.js
index 86305b8..927f260 100644
--- a/test/mjsunit/regress/regress-2790.js
+++ b/test/mjsunit/regress/regress-2790.js
@@ -26,6 +26,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Test that we can create arrays of any size.
-for (var i = 1000; i < 1000000; i += 97) {
+for (var i = 1000; i < 1000000; i += 197) {
new Array(i);
}
diff --git a/test/mjsunit/regress/regress-json-stringify-gc.js b/test/mjsunit/regress/regress-json-stringify-gc.js
index 4b355ae..905ab40 100644
--- a/test/mjsunit/regress/regress-json-stringify-gc.js
+++ b/test/mjsunit/regress/regress-json-stringify-gc.js
@@ -26,9 +26,9 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
var a = [];
-var new_space_string = "";
-for (var i = 0; i < 128; i++) {
- new_space_string += String.fromCharCode((Math.random() * 26 + 65) | 0);
+var new_space_string = "a";
+for (var i = 0; i < 8; i++) {
+ new_space_string += new_space_string;
}
for (var i = 0; i < 10000; i++) a.push(new_space_string);
@@ -40,12 +40,12 @@
assertTrue(json1 == json2, "GC caused JSON.stringify to fail.");
// Check that the slow path of JSON.stringify works correctly wrt GC.
-for (var i = 0; i < 100000; i++) {
+for (var i = 0; i < 10000; i++) {
var s = i.toString();
assertEquals('"' + s + '"', JSON.stringify(s, null, 0));
}
-for (var i = 0; i < 100000; i++) {
+for (var i = 0; i < 10000; i++) {
var s = i.toString() + "\u2603";
assertEquals('"' + s + '"', JSON.stringify(s, null, 0));
}
diff --git a/test/mozilla/mozilla.status b/test/mozilla/mozilla.status
index d5e851c..fdea0a9 100644
--- a/test/mozilla/mozilla.status
+++ b/test/mozilla/mozilla.status
@@ -81,23 +81,23 @@
# This takes a long time to run (~100 seconds). It should only be run
# by the really patient.
- 'js1_5/GC/regress-324278': [SLOW],
+ 'js1_5/GC/regress-324278': [SKIP],
# This takes a long time to run because our indexOf operation is
# pretty slow - it causes a lot of GCs; see issue
# #926379. We could consider marking this SKIP because it takes a
# while to run to completion.
- 'js1_5/GC/regress-338653': [SLOW],
+ 'js1_5/GC/regress-338653': [SKIP],
# This test is designed to run until it runs out of memory. This takes
# a very long time because it builds strings character by character
# and compiles a lot of regular expressions. We could consider marking
# this SKIP because it takes a while to run to completion.
- 'js1_5/GC/regress-346794': [SLOW],
+ 'js1_5/GC/regress-346794': [SKIP],
# Runs out of memory while trying to build huge string of 'x'
# characters. This takes a long time to run (~32 seconds).
- 'js1_5/GC/regress-348532': [SLOW],
+ 'js1_5/GC/regress-348532': [SKIP],
##################### FLAKY TESTS #####################
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index 65d5fb8..37fd407 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -113,10 +113,15 @@
'dependencies': [
'mksnapshot.<(v8_target_arch)#host',
'js2c#host',
+ 'generate_trig_table#host',
],
}, {
'toolsets': ['target'],
- 'dependencies': ['mksnapshot.<(v8_target_arch)', 'js2c'],
+ 'dependencies': [
+ 'mksnapshot.<(v8_target_arch)',
+ 'js2c',
+ 'generate_trig_table',
+ ],
}],
['component=="shared_library"', {
'defines': [
@@ -189,10 +194,10 @@
'conditions': [
['want_separate_host_toolset==1', {
'toolsets': ['host', 'target'],
- 'dependencies': ['js2c#host'],
+ 'dependencies': ['js2c#host', 'generate_trig_table#host'],
}, {
'toolsets': ['target'],
- 'dependencies': ['js2c'],
+ 'dependencies': ['js2c', 'generate_trig_table'],
}],
['component=="shared_library"', {
'defines': [
@@ -206,7 +211,7 @@
'type': 'none',
'conditions': [
['want_separate_host_toolset==1', {
- 'toolsets': ['host', 'target'],
+ 'toolsets': ['host'],
}, {
'toolsets': ['target'],
}],
@@ -231,9 +236,6 @@
{
'target_name': 'v8_base.<(v8_target_arch)',
'type': 'static_library',
- 'dependencies': [
- 'generate_trig_table',
- ],
'variables': {
'optimize': 'max',
},
diff --git a/tools/merge-to-branch.sh b/tools/merge-to-branch.sh
index 260dc8a..0314cb4 100755
--- a/tools/merge-to-branch.sh
+++ b/tools/merge-to-branch.sh
@@ -69,8 +69,9 @@
}
########## Option parsing
+REVERT_FROM_BLEEDING_EDGE=0
-while getopts ":hs:fp:rm:" OPTION ; do
+while getopts ":hs:fp:rm:R" OPTION ; do
case $OPTION in
h) usage
exit 0
@@ -85,6 +86,9 @@
;;
s) START_STEP=$OPTARG
;;
+ R) REVERSE_PATCH="--reverse"
+ REVERT_FROM_BLEEDING_EDGE=1
+ ;;
?) echo "Illegal option: -$OPTARG"
usage
exit 1
@@ -104,7 +108,8 @@
initial_environment_checks
if [ $START_STEP -le $CURRENT_STEP ] ; then
- if [ ${#@} -lt 2 ] ; then
+ let MIN_EXPECTED_ARGS=2-$REVERT_FROM_BLEEDING_EDGE
+ if [ ${#@} -lt $MIN_EXPECTED_ARGS ] ; then
if [ -z "$EXTRA_PATCH" ] ; then
die "Either a patch file or revision numbers must be specified"
fi
@@ -113,9 +118,13 @@
fi
fi
echo ">>> Step $CURRENT_STEP: Preparation"
- MERGE_TO_BRANCH=$1
- [[ -n "$MERGE_TO_BRANCH" ]] || die "Please specify a branch to merge to"
- shift
+ if [ $REVERT_FROM_BLEEDING_EDGE==1 ] ; then
+ MERGE_TO_BRANCH="bleeding_edge"
+ else
+ MERGE_TO_BRANCH=$1
+ [[ -n "$MERGE_TO_BRANCH" ]] || die "Please specify a branch to merge to"
+ shift
+ fi
persist "MERGE_TO_BRANCH"
common_prepare
fi
@@ -144,7 +153,11 @@
done
if [ -n "$REVISION_LIST" ] ; then
if [ -n "$REVERSE_PATCH" ] ; then
- NEW_COMMIT_MSG="Rollback of$REVISION_LIST in $MERGE_TO_BRANCH branch."
+ if [ $REVERT_FROM_BLEEDING_EDGE -eq 0 ] ; then
+ NEW_COMMIT_MSG="Rollback of$REVISION_LIST in $MERGE_TO_BRANCH branch."
+ else
+ NEW_COMMIT_MSG="Revert$REVISION_LIST."
+ fi
else
NEW_COMMIT_MSG="Merged$REVISION_LIST into $MERGE_TO_BRANCH branch."
fi;
@@ -189,14 +202,14 @@
fi
let CURRENT_STEP+=1
-if [ $START_STEP -le $CURRENT_STEP ] ; then
+if [ $START_STEP -le $CURRENT_STEP ] && [ $REVERT_FROM_BLEEDING_EDGE -eq 0 ] ; then
echo ">>> Step $CURRENT_STEP: Prepare $VERSION_FILE."
# These version numbers are used again for creating the tag
read_and_persist_version
fi
let CURRENT_STEP+=1
-if [ $START_STEP -le $CURRENT_STEP ] ; then
+if [ $START_STEP -le $CURRENT_STEP ] && [ $REVERT_FROM_BLEEDING_EDGE -eq 0 ] ; then
echo ">>> Step $CURRENT_STEP: Increment version number."
restore_if_unset "PATCH"
NEWPATCH=$(($PATCH + 1))
@@ -234,7 +247,7 @@
fi
let CURRENT_STEP+=1
-if [ $START_STEP -le $CURRENT_STEP ] ; then
+if [ $START_STEP -le $CURRENT_STEP ] && [ $REVERT_FROM_BLEEDING_EDGE -eq 0 ] ; then
echo ">>> Step $CURRENT_STEP: Determine svn commit revision"
restore_if_unset "NEW_COMMIT_MSG"
restore_if_unset "MERGE_TO_BRANCH"
@@ -248,7 +261,7 @@
fi
let CURRENT_STEP+=1
-if [ $START_STEP -le $CURRENT_STEP ] ; then
+if [ $START_STEP -le $CURRENT_STEP ] && [ $REVERT_FROM_BLEEDING_EDGE -eq 0 ] ; then
echo ">>> Step $CURRENT_STEP: Create the tag."
restore_if_unset "SVN_REVISION"
restore_version_if_unset "NEW"
@@ -273,9 +286,11 @@
restore_if_unset "REVISION_LIST"
restore_version_if_unset "NEW"
common_cleanup
- echo "*** SUMMARY ***"
- echo "version: $NEWMAJOR.$NEWMINOR.$NEWBUILD.$NEWPATCH"
- echo "branch: $TO_URL"
- echo "svn revision: $SVN_REVISION"
- [[ -n "$REVISION_LIST" ]] && echo "patches:$REVISION_LIST"
+ if [ $REVERT_FROM_BLEEDING_EDGE==0 ] ; then
+ echo "*** SUMMARY ***"
+ echo "version: $NEWMAJOR.$NEWMINOR.$NEWBUILD.$NEWPATCH"
+ echo "branch: $TO_URL"
+ echo "svn revision: $SVN_REVISION"
+ [[ -n "$REVISION_LIST" ]] && echo "patches:$REVISION_LIST"
+ fi
fi
diff --git a/tools/push-to-trunk/common_includes.py b/tools/push-to-trunk/common_includes.py
index eaa3d20..4f77c6b 100644
--- a/tools/push-to-trunk/common_includes.py
+++ b/tools/push-to-trunk/common_includes.py
@@ -99,8 +99,8 @@
result = ""
added_titles = set()
for (title, body, author) in commit_messages:
- # TODO(machenbach): Reload the commit description from rietveld in order to
- # catch late changes.
+ # TODO(machenbach): Better check for reverts. A revert should remove the
+ # original CL from the actual log entry.
title = title.strip()
if auto_format:
# Only add commits that set the LOG flag correctly.
@@ -114,16 +114,12 @@
if title in added_titles:
continue
- # TODO(machenbach): Let python do all formatting. Get raw git title, attach
- # issue and add/move dot to the end - all in one line. Make formatting and
- # indentation afterwards.
-
- # Add the commit's title line.
- result += "%s\n" % Fill80(title)
+ # Add and format the commit's title and bug reference. Move dot to the end.
added_titles.add(title)
-
- # Add bug references.
- result += MakeChangeLogBugReference(body)
+ raw_title = re.sub(r"(\.|\?|!)$", "", title)
+ bug_reference = MakeChangeLogBugReference(body)
+ space = " " if bug_reference else ""
+ result += "%s\n" % Fill80("%s%s%s." % (raw_title, space, bug_reference))
# Append the commit's author for reference if not in auto-format mode.
if not auto_format:
@@ -169,8 +165,7 @@
FormatIssues("Chromium ", crbugs)
if len(bug_groups) > 0:
- # Format with 8 characters indentation and max 80 character lines.
- return "%s\n" % Fill80("(%s)" % ", ".join(bug_groups))
+ return "(%s)" % ", ".join(bug_groups)
else:
return ""
diff --git a/tools/push-to-trunk/push_to_trunk.py b/tools/push-to-trunk/push_to_trunk.py
index 24dfb67..d78aacb 100755
--- a/tools/push-to-trunk/push_to_trunk.py
+++ b/tools/push-to-trunk/push_to_trunk.py
@@ -30,6 +30,7 @@
import optparse
import sys
import tempfile
+import urllib2
from common_includes import *
@@ -91,6 +92,21 @@
class PrepareChangeLog(Step):
MESSAGE = "Prepare raw ChangeLog entry."
+ def Reload(self, body):
+ """Attempts to reload the commit message from rietveld in order to allow
+ late changes to the LOG flag. Note: This is brittle to future changes of
+ the web page name or structure.
+ """
+ match = re.search(r"^Review URL: https://codereview\.chromium\.org/(\d+)$",
+ body, flags=re.M)
+ if match:
+ cl_url = "https://codereview.chromium.org/%s/description" % match.group(1)
+ try:
+ body = self.ReadURL(cl_url)
+ except urllib2.URLError:
+ pass
+ return body
+
def RunStep(self):
self.RestoreIfUnset("last_push")
@@ -112,7 +128,7 @@
commit_messages = [
[
self.Git("log -1 %s --format=\"%%s\"" % commit),
- self.Git("log -1 %s --format=\"%%B\"" % commit),
+ self.Reload(self.Git("log -1 %s --format=\"%%B\"" % commit)),
self.Git("log -1 %s --format=\"%%an\"" % commit),
] for commit in commits.splitlines()
]
@@ -151,6 +167,7 @@
changelog_entry = FileToText(self.Config(CHANGELOG_ENTRY_FILE)).rstrip()
changelog_entry = StripComments(changelog_entry)
changelog_entry = "\n".join(map(Fill80, changelog_entry.splitlines()))
+ changelog_entry = changelog_entry.lstrip()
if changelog_entry == "":
self.Die("Empty ChangeLog entry.")
@@ -541,6 +558,12 @@
if options.s < 0:
print "Bad step number %d" % options.s
return False
+ if options.f and not options.r:
+ print "A reviewer (-r) is required in forced mode."
+ return False
+ if options.f and not options.c:
+ print "A chromium checkout (-c) is required in forced mode."
+ return False
return True
diff --git a/tools/push-to-trunk/test_scripts.py b/tools/push-to-trunk/test_scripts.py
index 5e2340e..f4d0c12 100644
--- a/tools/push-to-trunk/test_scripts.py
+++ b/tools/push-to-trunk/test_scripts.py
@@ -71,14 +71,13 @@
["Title text 1",
"Title text 1\n\nBUG=\n",
"author1@chromium.org"],
- ["Title text 2",
+ ["Title text 2.",
"Title text 2\n\nBUG=1234\n",
"author2@chromium.org"],
]
- self.assertEquals(" Title text 1\n"
+ self.assertEquals(" Title text 1.\n"
" (author1@chromium.org)\n\n"
- " Title text 2\n"
- " (Chromium issue 1234)\n"
+ " Title text 2 (Chromium issue 1234).\n"
" (author2@chromium.org)\n\n",
MakeChangeLogBody(commits))
@@ -87,7 +86,7 @@
def testMakeChangeLogBodyAutoFormat(self):
commits = [
- ["Title text 1",
+ ["Title text 1!",
"Title text 1\nLOG=y\nBUG=\n",
"author1@chromium.org"],
["Title text 2",
@@ -100,9 +99,8 @@
"Title text 4\n\nBUG=1234\nLOG=\n",
"author4@chromium.org"],
]
- self.assertEquals(" Title text 1\n\n"
- " Title text 3\n"
- " (Chromium issue 1234)\n\n",
+ self.assertEquals(" Title text 1.\n\n"
+ " Title text 3 (Chromium issue 1234).\n\n",
MakeChangeLogBody(commits, True))
def testMakeChangeLogBugReferenceEmpty(self):
@@ -112,13 +110,13 @@
self.assertEquals("", MakeChangeLogBugReference("BUG=none\t"))
def testMakeChangeLogBugReferenceSimple(self):
- self.assertEquals(" (issue 987654)\n",
+ self.assertEquals("(issue 987654)",
MakeChangeLogBugReference("BUG = v8:987654"))
- self.assertEquals(" (Chromium issue 987654)\n",
+ self.assertEquals("(Chromium issue 987654)",
MakeChangeLogBugReference("BUG=987654 "))
def testMakeChangeLogBugReferenceFromBody(self):
- self.assertEquals(" (Chromium issue 1234567)\n",
+ self.assertEquals("(Chromium issue 1234567)",
MakeChangeLogBugReference("Title\n\nTBR=\nBUG=\n"
" BUG=\tchromium:1234567\t\n"
"R=somebody\n"))
@@ -126,54 +124,56 @@
def testMakeChangeLogBugReferenceMultiple(self):
# All issues should be sorted and grouped. Multiple references to the same
# issue should be filtered.
- self.assertEquals(" (issues 123, 234, Chromium issue 345)\n",
+ self.assertEquals("(issues 123, 234, Chromium issue 345)",
MakeChangeLogBugReference("Title\n\n"
"BUG=v8:234\n"
" BUG\t= 345, \tv8:234,\n"
"BUG=v8:123\n"
"R=somebody\n"))
- self.assertEquals(" (Chromium issues 123, 234)\n",
+ self.assertEquals("(Chromium issues 123, 234)",
MakeChangeLogBugReference("Title\n\n"
"BUG=234,,chromium:123 \n"
"R=somebody\n"))
- self.assertEquals(" (Chromium issues 123, 234)\n",
+ self.assertEquals("(Chromium issues 123, 234)",
MakeChangeLogBugReference("Title\n\n"
"BUG=chromium:234, , 123\n"
"R=somebody\n"))
- self.assertEquals(" (issues 345, 456)\n",
+ self.assertEquals("(issues 345, 456)",
MakeChangeLogBugReference("Title\n\n"
"\t\tBUG=v8:345,v8:456\n"
"R=somebody\n"))
- self.assertEquals(" (issue 123, Chromium issues 345, 456)\n",
+ self.assertEquals("(issue 123, Chromium issues 345, 456)",
MakeChangeLogBugReference("Title\n\n"
"BUG=chromium:456\n"
"BUG = none\n"
"R=somebody\n"
"BUG=456,v8:123, 345"))
+ # TODO(machenbach): These test don't make much sense when the formatting is
+ # done later.
def testMakeChangeLogBugReferenceLong(self):
# -----------------00--------10--------20--------30--------
- self.assertEquals(" (issues 234, 1234567890, 1234567"
- "8901234567890, Chromium issues 12345678,\n"
- " 123456789)\n",
+ self.assertEquals("(issues 234, 1234567890, 1234567"
+ "8901234567890, Chromium issues 12345678,"
+ " 123456789)",
MakeChangeLogBugReference("BUG=v8:234\n"
"BUG=v8:1234567890\n"
"BUG=v8:12345678901234567890\n"
"BUG=123456789\n"
"BUG=12345678\n"))
# -----------------00--------10--------20--------30--------
- self.assertEquals(" (issues 234, 1234567890, 1234567"
- "8901234567890, Chromium issues\n"
- " 123456789, 1234567890)\n",
+ self.assertEquals("(issues 234, 1234567890, 1234567"
+ "8901234567890, Chromium issues"
+ " 123456789, 1234567890)",
MakeChangeLogBugReference("BUG=v8:234\n"
"BUG=v8:12345678901234567890\n"
"BUG=v8:1234567890\n"
"BUG=123456789\n"
"BUG=1234567890\n"))
# -----------------00--------10--------20--------30--------
- self.assertEquals(" (Chromium issues 234, 1234567890"
- ", 12345678901234567,\n"
- " 1234567890123456789)\n",
+ self.assertEquals("(Chromium issues 234, 1234567890"
+ ", 12345678901234567, "
+ "1234567890123456789)",
MakeChangeLogBugReference("BUG=234\n"
"BUG=12345678901234567\n"
"BUG=1234567890123456789\n"
@@ -194,7 +194,7 @@
try:
expected_call = self._recipe[self._index]
except IndexError:
- raise Exception("Calling %s %s" % (name, " ".join(args)))
+ raise Exception("Calling %s %s" % (self._name, " ".join(args)))
# Pack expectations without arguments into a list.
if not isinstance(expected_call, list):
@@ -397,16 +397,27 @@
TEST_CONFIG[CHANGELOG_ENTRY_FILE] = self.MakeEmptyTempFile()
self.ExpectGit([
- ["log 1234..HEAD --format=%H", "rev1\nrev2\nrev3"],
+ ["log 1234..HEAD --format=%H", "rev1\nrev2\nrev3\nrev4"],
["log -1 rev1 --format=\"%s\"", "Title text 1"],
["log -1 rev1 --format=\"%B\"", "Title\n\nBUG=\nLOG=y\n"],
["log -1 rev1 --format=\"%an\"", "author1@chromium.org"],
- ["log -1 rev2 --format=\"%s\"", "Title text 2"],
+ ["log -1 rev2 --format=\"%s\"", "Title text 2."],
["log -1 rev2 --format=\"%B\"", "Title\n\nBUG=123\nLOG= \n"],
["log -1 rev2 --format=\"%an\"", "author2@chromium.org"],
["log -1 rev3 --format=\"%s\"", "Title text 3"],
["log -1 rev3 --format=\"%B\"", "Title\n\nBUG=321\nLOG=true\n"],
["log -1 rev3 --format=\"%an\"", "author3@chromium.org"],
+ ["log -1 rev4 --format=\"%s\"", "Title text 4"],
+ ["log -1 rev4 --format=\"%B\"",
+ ("Title\n\nBUG=456\nLOG=Y\n\n"
+ "Review URL: https://codereview.chromium.org/9876543210\n")],
+ ["log -1 rev4 --format=\"%an\"", "author4@chromium.org"],
+ ])
+
+ # The cl for rev4 on rietveld has an updated LOG flag.
+ self.ExpectReadURL([
+ ["https://codereview.chromium.org/9876543210/description",
+ "Title\n\nBUG=456\nLOG=N\n\n"],
])
self.MakeStep().Persist("last_push", "1234")
@@ -418,10 +429,9 @@
# comparison here instead of a regexp match.
expected_cl = """\\d+\\-\\d+\\-\\d+: Version 3\\.22\\.5
- Title text 1
+ Title text 1.
- Title text 3
- \\(Chromium issue 321\\)
+ Title text 3 \\(Chromium issue 321\\).
Performance and stability improvements on all platforms\\.
#
@@ -429,17 +439,18 @@
# commit messages from the list below are included\\.
# All lines starting with # will be stripped\\.
#
-# Title text 1
+# Title text 1.
# \\(author1@chromium\\.org\\)
#
-# Title text 2
-# \\(Chromium issue 123\\)
+# Title text 2 \\(Chromium issue 123\\).
# \\(author2@chromium\\.org\\)
#
-# Title text 3
-# \\(Chromium issue 321\\)
+# Title text 3 \\(Chromium issue 321\\).
# \\(author3@chromium\\.org\\)
#
+# Title text 4 \\(Chromium issue 456\\).
+# \\(author4@chromium\\.org\\)
+#
#"""
self.assertTrue(re.match(expected_cl, actual_cl))
@@ -461,7 +472,7 @@
self.MakeStep(EditChangeLog).Run()
- self.assertEquals(" New\n Lines\n\n\n Original CL",
+ self.assertEquals("New\n Lines\n\n\n Original CL",
FileToText(TEST_CONFIG[CHANGELOG_FILE]))
def testIncrementVersion(self):
@@ -539,8 +550,7 @@
def CheckPreparePush():
cl = FileToText(TEST_CONFIG[CHANGELOG_FILE])
self.assertTrue(re.search(r"Version 3.22.5", cl))
- self.assertTrue(re.search(r" Log text 1", cl))
- self.assertTrue(re.search(r" \(issue 321\)", cl))
+ self.assertTrue(re.search(r" Log text 1 \(issue 321\).", cl))
self.assertFalse(re.search(r" \(author1@chromium\.org\)", cl))
# Make sure all comments got stripped.
@@ -555,7 +565,7 @@
def CheckSVNCommit():
commit = FileToText(TEST_CONFIG[COMMITMSG_FILE])
self.assertTrue(re.search(r"Version 3.22.5", commit))
- self.assertTrue(re.search(r"Log text 1. \(issue 321\)", commit))
+ self.assertTrue(re.search(r"Log text 1 \(issue 321\).", commit))
version = FileToText(TEST_CONFIG[VERSION_FILE])
self.assertTrue(re.search(r"#define MINOR_VERSION\s+22", version))
self.assertTrue(re.search(r"#define BUILD_NUMBER\s+5", version))
@@ -643,9 +653,8 @@
self.assertTrue(re.search("\"v8_revision\": \"123456\"", deps))
cl = FileToText(TEST_CONFIG[CHANGELOG_FILE])
- self.assertTrue(re.search(r"\d\d\d\d\-\d+\-\d+: Version 3\.22\.5", cl))
- self.assertTrue(re.search(r" Log text 1", cl))
- self.assertTrue(re.search(r" \(issue 321\)", cl))
+ self.assertTrue(re.search(r"^\d\d\d\d\-\d+\-\d+: Version 3\.22\.5", cl))
+ self.assertTrue(re.search(r" Log text 1 \(issue 321\).", cl))
self.assertTrue(re.search(r"1999\-04\-05: Version 3\.22\.4", cl))
# Note: The version file is on build number 5 again in the end of this test
@@ -686,3 +695,27 @@
self.assertEquals("100", self.MakeStep().Restore("lkgr"))
self.assertEquals("101", self.MakeStep().Restore("latest"))
+
+
+class SystemTest(unittest.TestCase):
+ def testReload(self):
+ step = MakeStep(step_class=PrepareChangeLog, number=0, state={}, config={},
+ options=None,
+ side_effect_handler=DEFAULT_SIDE_EFFECT_HANDLER)
+ body = step.Reload(
+"""------------------------------------------------------------------------
+r17997 | machenbach@chromium.org | 2013-11-22 11:04:04 +0100 (...) | 6 lines
+
+Prepare push to trunk. Now working on version 3.23.11.
+
+R=danno@chromium.org
+
+Review URL: https://codereview.chromium.org/83173002
+
+------------------------------------------------------------------------""")
+ self.assertEquals(
+"""Prepare push to trunk. Now working on version 3.23.11.
+
+R=danno@chromium.org
+
+Committed: https://code.google.com/p/v8/source/detail?r=17997""", body)
diff --git a/tools/run-tests.py b/tools/run-tests.py
index 2fdbeb9..32b3f49 100755
--- a/tools/run-tests.py
+++ b/tools/run-tests.py
@@ -53,9 +53,13 @@
"release" : 1 }
# Use this to run several variants of the tests.
-VARIANT_FLAGS = [[],
- ["--stress-opt", "--always-opt"],
- ["--nocrankshaft"]]
+VARIANT_FLAGS = {
+ "default": [],
+ "stress": ["--stress-opt", "--always-opt"],
+ "nocrankshaft": ["--nocrankshaft"]}
+
+VARIANTS = ["default", "stress", "nocrankshaft"]
+
MODE_FLAGS = {
"debug" : ["--nobreak-on-abort", "--nodead-code-elimination",
"--nofold-constants", "--enable-slow-asserts",
@@ -97,6 +101,12 @@
result.add_option("--flaky-tests",
help="Regard tests marked as flaky (run|skip|dontcare)",
default="dontcare")
+ result.add_option("--slow-tests",
+ help="Regard slow tests (run|skip|dontcare)",
+ default="dontcare")
+ result.add_option("--pass-fail-tests",
+ help="Regard pass|fail tests (run|skip|dontcare)",
+ default="dontcare")
result.add_option("--command-prefix",
help="Prepended to each shell command used to run a test",
default="")
@@ -128,6 +138,8 @@
result.add_option("--no-variants", "--novariants",
help="Don't run any testing variants",
default=False, dest="no_variants", action="store_true")
+ result.add_option("--variants",
+ help="Comma-separated list of testing variants")
result.add_option("--outdir", help="Base directory with compile output",
default="out")
result.add_option("-p", "--progress",
@@ -167,6 +179,7 @@
def ProcessOptions(options):
global VARIANT_FLAGS
+ global VARIANTS
# Architecture and mode related stuff.
if options.arch_and_mode:
@@ -205,26 +218,41 @@
"""Returns true if zero or one of multiple arguments are true."""
return reduce(lambda x, y: x + y, args) <= 1
- if not excl(options.no_stress, options.stress_only, options.no_variants):
- print "Use only one of --no-stress, --stress-only or --no-variants."
+ if not excl(options.no_stress, options.stress_only, options.no_variants,
+ bool(options.variants)):
+ print("Use only one of --no-stress, --stress-only, --no-variants or "
+ "--variants.")
return False
if options.no_stress:
- VARIANT_FLAGS = [[], ["--nocrankshaft"]]
+ VARIANTS = ["default", "nocrankshaft"]
if options.no_variants:
- VARIANT_FLAGS = [[]]
+ VARIANTS = ["default"]
+ if options.stress_only:
+ VARIANTS = ["stress"]
+ if options.variants:
+ VARIANTS = options.variants.split(",")
+ if not set(VARIANTS).issubset(VARIANT_FLAGS.keys()):
+ print "All variants must be in %s" % str(VARIANT_FLAGS.keys())
+ return False
if not options.shell_dir:
if options.shell:
print "Warning: --shell is deprecated, use --shell-dir instead."
options.shell_dir = os.path.dirname(options.shell)
- if options.stress_only:
- VARIANT_FLAGS = [["--stress-opt", "--always-opt"]]
if options.valgrind:
run_valgrind = os.path.join("tools", "run-valgrind.py")
# This is OK for distributed running, so we don't need to set no_network.
options.command_prefix = (["python", "-u", run_valgrind] +
options.command_prefix)
- if not options.flaky_tests in ["run", "skip", "dontcare"]:
- print "Unknown flaky test mode %s" % options.flaky_tests
+ def CheckTestMode(name, option):
+ if not option in ["run", "skip", "dontcare"]:
+ print "Unknown %s mode %s" % (name, option)
+ return False
+ return True
+ if not CheckTestMode("flaky test", options.flaky_tests):
+ return False
+ if not CheckTestMode("slow test", options.slow_tests):
+ return False
+ if not CheckTestMode("pass|fail test", options.pass_fail_tests):
return False
if not options.no_i18n:
DEFAULT_TESTS.append("intl")
@@ -341,13 +369,15 @@
if len(args) > 0:
s.FilterTestCasesByArgs(args)
all_tests += s.tests
- s.FilterTestCasesByStatus(options.warn_unused, options.flaky_tests)
+ s.FilterTestCasesByStatus(options.warn_unused, options.flaky_tests,
+ options.slow_tests, options.pass_fail_tests)
if options.cat:
verbose.PrintTestSource(s.tests)
continue
+ variant_flags = [VARIANT_FLAGS[var] for var in VARIANTS]
s.tests = [ t.CopyAddingFlags(v)
for t in s.tests
- for v in s.VariantFlags(t, VARIANT_FLAGS) ]
+ for v in s.VariantFlags(t, variant_flags) ]
s.tests = ShardTests(s.tests, options.shard_count, options.shard_run)
num_tests += len(s.tests)
for t in s.tests:
diff --git a/tools/testrunner/local/statusfile.py b/tools/testrunner/local/statusfile.py
index da0c797..e290122 100644
--- a/tools/testrunner/local/statusfile.py
+++ b/tools/testrunner/local/statusfile.py
@@ -59,7 +59,11 @@
def DoSkip(outcomes):
- return SKIP in outcomes or SLOW in outcomes
+ return SKIP in outcomes
+
+
+def IsSlow(outcomes):
+ return SLOW in outcomes
def OnlyStandardVariant(outcomes):
diff --git a/tools/testrunner/local/testsuite.py b/tools/testrunner/local/testsuite.py
index 8517ce9..ff51196 100644
--- a/tools/testrunner/local/testsuite.py
+++ b/tools/testrunner/local/testsuite.py
@@ -93,11 +93,24 @@
def _FilterFlaky(flaky, mode):
return (mode == "run" and not flaky) or (mode == "skip" and flaky)
- def FilterTestCasesByStatus(self, warn_unused_rules, flaky_tests="dontcare"):
+ @staticmethod
+ def _FilterSlow(slow, mode):
+ return (mode == "run" and not slow) or (mode == "skip" and slow)
+
+ @staticmethod
+ def _FilterPassFail(pass_fail, mode):
+ return (mode == "run" and not pass_fail) or (mode == "skip" and pass_fail)
+
+ def FilterTestCasesByStatus(self, warn_unused_rules,
+ flaky_tests="dontcare",
+ slow_tests="dontcare",
+ pass_fail_tests="dontcare"):
filtered = []
used_rules = set()
for t in self.tests:
flaky = False
+ slow = False
+ pass_fail = False
testname = self.CommonTestName(t)
if testname in self.rules:
used_rules.add(testname)
@@ -107,6 +120,8 @@
if statusfile.DoSkip(t.outcomes):
continue # Don't add skipped tests to |filtered|.
flaky = statusfile.IsFlaky(t.outcomes)
+ slow = statusfile.IsSlow(t.outcomes)
+ pass_fail = statusfile.IsPassOrFail(t.outcomes)
skip = False
for rule in self.wildcards:
assert rule[-1] == '*'
@@ -117,7 +132,11 @@
skip = True
break # "for rule in self.wildcards"
flaky = flaky or statusfile.IsFlaky(t.outcomes)
- if skip or self._FilterFlaky(flaky, flaky_tests):
+ slow = slow or statusfile.IsSlow(t.outcomes)
+ pass_fail = pass_fail or statusfile.IsPassOrFail(t.outcomes)
+ if (skip or self._FilterFlaky(flaky, flaky_tests)
+ or self._FilterSlow(slow, slow_tests)
+ or self._FilterPassFail(pass_fail, pass_fail_tests)):
continue # "for t in self.tests"
filtered.append(t)
self.tests = filtered