Merge v8 from https://chromium.googlesource.com/external/v8.git at 5ae72c9d3193fcbb0e2640a2b74b2f1f0d1b05e9
This commit was generated by merge_from_chromium.py.
Change-Id: I3bf2ac32eaeef3a3997ee2b7197348aa1a190eb7
diff --git a/ChangeLog b/ChangeLog
index f3498c7..153f45c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2013-09-27: Version 3.22.3
+
+ Added methods to enable configuration of ResourceConstraints based on
+ limits derived at runtime.
+ (Chromium issue 292928)
+
+ Added -optimize-for-size flag to optimize for memory size (will be used
+ by pre-aging CL), and removed the is_memory_constrained
+ ResourceConstraint.
+ (Chromium issue 292928)
+
+ Performance and stability improvements on all platforms.
+
+
2013-09-26: Version 3.22.2
Performance and stability improvements on all platforms.
diff --git a/include/v8-defaults.h b/include/v8-defaults.h
new file mode 100644
index 0000000..381a482
--- /dev/null
+++ b/include/v8-defaults.h
@@ -0,0 +1,54 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_V8_DEFAULTS_H_
+#define V8_V8_DEFAULTS_H_
+
+#include "v8.h"
+
+/**
+ * Default configuration support for the V8 JavaScript engine.
+ */
+namespace v8 {
+
+/**
+ * Configures the constraints with reasonable default values based on the
+ * capabilities of the current device the VM is running on.
+ */
+bool V8_EXPORT ConfigureResourceConstraintsForCurrentPlatform(
+ ResourceConstraints* constraints);
+
+
+/**
+ * Convience function which performs SetResourceConstraints with the settings
+ * returned by ConfigureResourceConstraintsForCurrentPlatform.
+ */
+bool V8_EXPORT SetDefaultResourceConstraintsForCurrentPlatform();
+
+} // namespace v8
+
+#endif // V8_V8_DEFAULTS_H_
diff --git a/include/v8-testing.h b/include/v8-testing.h
index 97b467a..ba4fcc4 100644
--- a/include/v8-testing.h
+++ b/include/v8-testing.h
@@ -68,8 +68,4 @@
} // namespace v8
-
-#undef V8_EXPORT
-
-
#endif // V8_V8_TEST_H_
diff --git a/include/v8.h b/include/v8.h
index 62a1cb3..19abf0f 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -135,6 +135,7 @@
class ObjectOperationDescriptor;
class RawOperationDescriptor;
class CallHandlerHelper;
+class EscapableHandleScope;
namespace internal {
class Arguments;
@@ -377,7 +378,6 @@
* The referee is kept alive by the local handle even when
* the original handle is destroyed/disposed.
*/
- V8_INLINE static Local<T> New(Handle<T> that);
V8_INLINE static Local<T> New(Isolate* isolate, Handle<T> that);
template<class M>
V8_INLINE static Local<T> New(Isolate* isolate,
@@ -401,6 +401,7 @@
friend class Context;
template<class F> friend class internal::CustomArguments;
friend class HandleScope;
+ friend class EscapableHandleScope;
V8_INLINE static Local<T> New(Isolate* isolate, T* that);
};
@@ -773,10 +774,7 @@
~HandleScope();
- /**
- * Closes the handle scope and returns the value as a handle in the
- * previous scope, which is the new current scope after the call.
- */
+ // TODO(dcarney): deprecated - use EscapableHandleScope::Escape.
template <class T> Local<T> Close(Handle<T> value);
/**
@@ -784,16 +782,19 @@
*/
static int NumberOfHandles();
+ private:
/**
* Creates a new handle with the given value.
*/
- static internal::Object** CreateHandle(internal::Object* value);
static internal::Object** CreateHandle(internal::Isolate* isolate,
internal::Object* value);
- // Faster version, uses HeapObject to obtain the current Isolate.
- static internal::Object** CreateHandle(internal::HeapObject* value);
+ // Uses HeapObject to obtain the current Isolate.
+ static internal::Object** CreateHandle(internal::HeapObject* heap_object,
+ internal::Object* value);
- private:
+ V8_INLINE HandleScope() {}
+ void Initialize(Isolate* isolate);
+
// Make it hard to create heap-allocated or illegal handle scopes by
// disallowing certain operations.
HandleScope(const HandleScope&);
@@ -814,19 +815,58 @@
}
};
- void Initialize(Isolate* isolate);
void Leave();
internal::Isolate* isolate_;
internal::Object** prev_next_;
internal::Object** prev_limit_;
+ // TODO(dcarney): remove this field
// Allow for the active closing of HandleScopes which allows to pass a handle
// from the HandleScope being closed to the next top most HandleScope.
bool is_closed_;
internal::Object** RawClose(internal::Object** value);
friend class ImplementationUtilities;
+ friend class EscapableHandleScope;
+ template<class F> friend class Handle;
+ template<class F> friend class Local;
+ friend class Object;
+ friend class Context;
+};
+
+
+/**
+ * A HandleScope which first allocates a handle in the current scope
+ * which will be later filled with the escape value.
+ */
+class V8_EXPORT EscapableHandleScope : public HandleScope {
+ public:
+ EscapableHandleScope(Isolate* isolate);
+ V8_INLINE ~EscapableHandleScope() {}
+
+ /**
+ * Pushes the value into the previous scope and returns a handle to it.
+ * Cannot be called twice.
+ */
+ template <class T>
+ V8_INLINE Local<T> Escape(Local<T> value) {
+ internal::Object** slot =
+ Escape(reinterpret_cast<internal::Object**>(*value));
+ return Local<T>(reinterpret_cast<T*>(slot));
+ }
+
+ private:
+ internal::Object** Escape(internal::Object** escape_value);
+
+ // Make it hard to create heap-allocated or illegal handle scopes by
+ // disallowing certain operations.
+ EscapableHandleScope(const EscapableHandleScope&);
+ void operator=(const EscapableHandleScope&);
+ void* operator new(size_t size);
+ void operator delete(void*, size_t);
+
+ internal::Object** escape_slot_;
};
@@ -2386,13 +2426,13 @@
protected:
friend class internal::FunctionCallbackArguments;
friend class internal::CustomArguments<FunctionCallbackInfo>;
- static const int kReturnValueIndex = 0;
- static const int kReturnValueDefaultValueIndex = -1;
- static const int kIsolateIndex = -2;
- static const int kDataIndex = -3;
- static const int kCalleeIndex = -4;
- static const int kHolderIndex = -5;
- static const int kContextSaveIndex = -6;
+ static const int kContextSaveIndex = 0;
+ static const int kCalleeIndex = -1;
+ static const int kDataIndex = -2;
+ static const int kReturnValueIndex = -3;
+ static const int kReturnValueDefaultValueIndex = -4;
+ static const int kIsolateIndex = -5;
+ static const int kHolderIndex = -6;
V8_INLINE FunctionCallbackInfo(internal::Object** implicit_args,
internal::Object** values,
@@ -3762,23 +3802,18 @@
uint32_t* stack_limit() const { return stack_limit_; }
// Sets an address beyond which the VM's stack may not grow.
void set_stack_limit(uint32_t* value) { stack_limit_ = value; }
- Maybe<bool> is_memory_constrained() const { return is_memory_constrained_; }
- // If set to true, V8 will limit it's memory usage, at the potential cost of
- // lower performance. Note, this option is a tentative addition to the API
- // and may be removed or modified without warning.
- void set_memory_constrained(bool value) {
- is_memory_constrained_ = Maybe<bool>(value);
- }
private:
int max_young_space_size_;
int max_old_space_size_;
int max_executable_size_;
uint32_t* stack_limit_;
- Maybe<bool> is_memory_constrained_;
};
+/**
+ * Sets the given ResourceConstraints on the current isolate.
+ */
bool V8_EXPORT SetResourceConstraints(ResourceConstraints* constraints);
@@ -3791,12 +3826,7 @@
typedef void (*MessageCallback)(Handle<Message> message, Handle<Value> error);
-/**
- * Schedules an exception to be thrown when returning to JavaScript. When an
- * exception has been scheduled it is illegal to invoke any JavaScript
- * operation; the caller must return immediately and only after the exception
- * has been handled does it become legal to invoke JavaScript operations.
- */
+// TODO(dcarney): remove. Use Isolate::ThrowException instead.
Handle<Value> V8_EXPORT ThrowException(Handle<Value> exception);
/**
@@ -4052,6 +4082,14 @@
Local<Context> GetEnteredContext();
/**
+ * Schedules an exception to be thrown when returning to JavaScript. When an
+ * exception has been scheduled it is illegal to invoke any JavaScript
+ * operation; the caller must return immediately and only after the exception
+ * has been handled does it become legal to invoke JavaScript operations.
+ */
+ Local<Value> ThrowException(Local<Value> exception);
+
+ /**
* Allows the host application to group objects together. If one
* object in the group is alive, all objects in the group are alive.
* After each garbage collection, object groups are removed. It is
@@ -5425,7 +5463,7 @@
static const int kUndefinedOddballKind = 5;
static const int kNullOddballKind = 3;
- static void CheckInitializedImpl(v8::Isolate* isolate);
+ V8_EXPORT static void CheckInitializedImpl(v8::Isolate* isolate);
V8_INLINE static void CheckInitialized(v8::Isolate* isolate) {
#ifdef V8_ENABLE_CHECKS
CheckInitializedImpl(isolate);
@@ -5541,19 +5579,6 @@
template <class T>
-Local<T> Local<T>::New(Handle<T> that) {
- if (that.IsEmpty()) return Local<T>();
- T* that_ptr = *that;
- internal::Object** p = reinterpret_cast<internal::Object**>(that_ptr);
- if (internal::Internals::CanCastToHeapObject(that_ptr)) {
- return Local<T>(reinterpret_cast<T*>(HandleScope::CreateHandle(
- reinterpret_cast<internal::HeapObject*>(*p))));
- }
- return Local<T>(reinterpret_cast<T*>(HandleScope::CreateHandle(*p)));
-}
-
-
-template <class T>
Local<T> Local<T>::New(Isolate* isolate, Handle<T> that) {
return New(isolate, that.val_);
}
@@ -5894,7 +5919,7 @@
template<typename T>
Local<Value> FunctionCallbackInfo<T>::operator[](int i) const {
- if (i < 0 || length_ <= i) return Local<Value>(*Undefined());
+ if (i < 0 || length_ <= i) return Local<Value>(*Undefined(GetIsolate()));
return Local<Value>(reinterpret_cast<Value*>(values_ - i));
}
@@ -5976,7 +6001,8 @@
Handle<Boolean> Boolean::New(bool value) {
- return value ? True() : False();
+ Isolate* isolate = Isolate::GetCurrent();
+ return value ? True(isolate) : False(isolate);
}
@@ -5988,6 +6014,7 @@
Local<Value> Object::GetInternalField(int index) {
#ifndef V8_ENABLE_CHECKS
typedef internal::Object O;
+ typedef internal::HeapObject HO;
typedef internal::Internals I;
O* obj = *reinterpret_cast<O**>(this);
// Fast path: If the object is a plain JSObject, which is the common case, we
@@ -5995,7 +6022,7 @@
if (I::GetInstanceType(obj) == I::kJSObjectType) {
int offset = I::kJSObjectHeaderSize + (internal::kApiPointerSize * index);
O* value = I::ReadField<O*>(obj, offset);
- O** result = HandleScope::CreateHandle(value);
+ O** result = HandleScope::CreateHandle(reinterpret_cast<HO*>(obj), value);
return Local<Value>(reinterpret_cast<Value*>(result));
}
#endif
@@ -6447,8 +6474,11 @@
Local<Value> Context::GetEmbedderData(int index) {
#ifndef V8_ENABLE_CHECKS
typedef internal::Object O;
+ typedef internal::HeapObject HO;
typedef internal::Internals I;
- O** result = HandleScope::CreateHandle(I::ReadEmbedderData<O*>(this, index));
+ HO* context = *reinterpret_cast<HO**>(this);
+ O** result =
+ HandleScope::CreateHandle(context, I::ReadEmbedderData<O*>(this, index));
return Local<Value>(reinterpret_cast<Value*>(result));
#else
return SlowGetEmbedderData(index);
diff --git a/samples/lineprocessor.cc b/samples/lineprocessor.cc
index b4ffb44..5068c88 100644
--- a/samples/lineprocessor.cc
+++ b/samples/lineprocessor.cc
@@ -296,7 +296,7 @@
v8::HandleScope handle_scope(isolate);
v8::Handle<v8::String> input_line = ReadLine();
- if (input_line == v8::Undefined()) {
+ if (input_line == v8::Undefined(isolate)) {
continue;
}
@@ -417,7 +417,7 @@
// function is called. Reads a string from standard input and returns.
void ReadLine(const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() > 0) {
- v8::ThrowException(v8::String::New("Unexpected arguments"));
+ args.GetIsolate()->ThrowException(v8::String::New("Unexpected arguments"));
return;
}
args.GetReturnValue().Set(ReadLine());
@@ -436,7 +436,7 @@
res = fgets(buffer, kBufferSize, stdin);
}
if (res == NULL) {
- v8::Handle<v8::Primitive> t = v8::Undefined();
+ v8::Handle<v8::Primitive> t = v8::Undefined(v8::Isolate::GetCurrent());
return v8::Handle<v8::String>::Cast(t);
}
// Remove newline char
diff --git a/samples/shell.cc b/samples/shell.cc
index 710547c..06bd8f6 100644
--- a/samples/shell.cc
+++ b/samples/shell.cc
@@ -140,17 +140,20 @@
// the argument into a JavaScript string.
void Read(const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() != 1) {
- v8::ThrowException(v8::String::New("Bad parameters"));
+ args.GetIsolate()->ThrowException(
+ v8::String::New("Bad parameters"));
return;
}
v8::String::Utf8Value file(args[0]);
if (*file == NULL) {
- v8::ThrowException(v8::String::New("Error loading file"));
+ args.GetIsolate()->ThrowException(
+ v8::String::New("Error loading file"));
return;
}
v8::Handle<v8::String> source = ReadFile(*file);
if (source.IsEmpty()) {
- v8::ThrowException(v8::String::New("Error loading file"));
+ args.GetIsolate()->ThrowException(
+ v8::String::New("Error loading file"));
return;
}
args.GetReturnValue().Set(source);
@@ -165,12 +168,14 @@
v8::HandleScope handle_scope(args.GetIsolate());
v8::String::Utf8Value file(args[i]);
if (*file == NULL) {
- v8::ThrowException(v8::String::New("Error loading file"));
+ args.GetIsolate()->ThrowException(
+ v8::String::New("Error loading file"));
return;
}
v8::Handle<v8::String> source = ReadFile(*file);
if (source.IsEmpty()) {
- v8::ThrowException(v8::String::New("Error loading file"));
+ args.GetIsolate()->ThrowException(
+ v8::String::New("Error loading file"));
return;
}
if (!ExecuteString(args.GetIsolate(),
@@ -178,7 +183,8 @@
v8::String::New(*file),
false,
false)) {
- v8::ThrowException(v8::String::New("Error executing file"));
+ args.GetIsolate()->ThrowException(
+ v8::String::New("Error executing file"));
return;
}
}
diff --git a/src/api.cc b/src/api.cc
index 6eb3789..6d62749 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -473,16 +473,7 @@
v8::Handle<Value> ThrowException(v8::Handle<v8::Value> value) {
- i::Isolate* isolate = i::Isolate::Current();
- ENTER_V8(isolate);
- // If we're passed an empty handle, we throw an undefined exception
- // to deal more gracefully with out of memory situations.
- if (value.IsEmpty()) {
- isolate->ScheduleThrow(isolate->heap()->undefined_value());
- } else {
- isolate->ScheduleThrow(*Utils::OpenHandle(*value));
- }
- return v8::Undefined();
+ return v8::Isolate::GetCurrent()->ThrowException(value);
}
@@ -572,8 +563,7 @@
: max_young_space_size_(0),
max_old_space_size_(0),
max_executable_size_(0),
- stack_limit_(NULL),
- is_memory_constrained_() { }
+ stack_limit_(NULL) { }
bool SetResourceConstraints(ResourceConstraints* constraints) {
@@ -594,11 +584,6 @@
uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit());
isolate->stack_guard()->SetStackLimit(limit);
}
- if (constraints->is_memory_constrained().has_value &&
- !i::FLAG_force_memory_constrained.has_value) {
- isolate->set_is_memory_constrained(
- constraints->is_memory_constrained().value);
- }
return true;
}
@@ -698,21 +683,35 @@
}
-i::Object** HandleScope::CreateHandle(i::Object* value) {
- return i::HandleScope::CreateHandle(i::Isolate::Current(), value);
-}
-
-
i::Object** HandleScope::CreateHandle(i::Isolate* isolate, i::Object* value) {
- ASSERT(isolate == i::Isolate::Current());
return i::HandleScope::CreateHandle(isolate, value);
}
-i::Object** HandleScope::CreateHandle(i::HeapObject* value) {
- ASSERT(value->IsHeapObject());
- return reinterpret_cast<i::Object**>(
- i::HandleScope::CreateHandle(value->GetIsolate(), value));
+i::Object** HandleScope::CreateHandle(i::HeapObject* heap_object,
+ i::Object* value) {
+ ASSERT(heap_object->IsHeapObject());
+ return i::HandleScope::CreateHandle(heap_object->GetIsolate(), value);
+}
+
+
+EscapableHandleScope::EscapableHandleScope(Isolate* v8_isolate) {
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
+ escape_slot_ = CreateHandle(isolate, isolate->heap()->the_hole_value());
+ Initialize(v8_isolate);
+}
+
+
+i::Object** EscapableHandleScope::Escape(i::Object** escape_value) {
+ ApiCheck(*escape_slot_ == isolate_->heap()->the_hole_value(),
+ "EscapeableHandleScope::Escape",
+ "Escape value set twice");
+ if (escape_value == NULL) {
+ *escape_slot_ = isolate_->heap()->undefined_value();
+ return NULL;
+ }
+ *escape_slot_ = *escape_value;
+ return escape_slot_;
}
@@ -1019,7 +1018,9 @@
}
obj->set_serial_number(i::Smi::FromInt(next_serial_number));
if (callback != 0) {
- if (data.IsEmpty()) data = v8::Undefined();
+ if (data.IsEmpty()) {
+ data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
+ }
Utils::ToLocal(obj)->SetCallHandler(callback, data);
}
obj->set_length(length);
@@ -1243,7 +1244,9 @@
i::Handle<i::CallHandlerInfo> obj =
i::Handle<i::CallHandlerInfo>::cast(struct_obj);
SET_FIELD_WRAPPED(obj, set_callback, callback);
- if (data.IsEmpty()) data = v8::Undefined();
+ if (data.IsEmpty()) {
+ data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
+ }
obj->set_data(*Utils::OpenHandle(*data));
Utils::OpenHandle(this)->set_call_code(*obj);
}
@@ -1281,7 +1284,9 @@
isolate->factory()->NewExecutableAccessorInfo();
SET_FIELD_WRAPPED(obj, set_getter, getter);
SET_FIELD_WRAPPED(obj, set_setter, setter);
- if (data.IsEmpty()) data = v8::Undefined();
+ if (data.IsEmpty()) {
+ data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
+ }
obj->set_data(*Utils::OpenHandle(*data));
return SetAccessorInfoProperties(obj, name, settings, attributes, signature);
}
@@ -1509,7 +1514,9 @@
if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
- if (data.IsEmpty()) data = v8::Undefined();
+ if (data.IsEmpty()) {
+ data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
+ }
obj->set_data(*Utils::OpenHandle(*data));
cons->set_named_property_handler(*obj);
}
@@ -1545,7 +1552,9 @@
SET_FIELD_WRAPPED(info, set_named_callback, named_callback);
SET_FIELD_WRAPPED(info, set_indexed_callback, indexed_callback);
- if (data.IsEmpty()) data = v8::Undefined();
+ if (data.IsEmpty()) {
+ data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
+ }
info->set_data(*Utils::OpenHandle(*data));
i::FunctionTemplateInfo* constructor =
@@ -1581,7 +1590,9 @@
if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
- if (data.IsEmpty()) data = v8::Undefined();
+ if (data.IsEmpty()) {
+ data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
+ }
obj->set_data(*Utils::OpenHandle(*data));
cons->set_indexed_property_handler(*obj);
}
@@ -1601,7 +1612,9 @@
i::Handle<i::CallHandlerInfo> obj =
i::Handle<i::CallHandlerInfo>::cast(struct_obj);
SET_FIELD_WRAPPED(obj, set_callback, callback);
- if (data.IsEmpty()) data = v8::Undefined();
+ if (data.IsEmpty()) {
+ data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
+ }
obj->set_data(*Utils::OpenHandle(*data));
cons->set_instance_call_handler(*obj);
}
@@ -1706,8 +1719,9 @@
static_cast<int>(origin->ResourceColumnOffset()->Value());
}
if (!origin->ResourceIsSharedCrossOrigin().IsEmpty()) {
+ v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
is_shared_cross_origin =
- origin->ResourceIsSharedCrossOrigin() == v8::True();
+ origin->ResourceIsSharedCrossOrigin() == v8::True(v8_isolate);
}
}
EXCEPTION_PREAMBLE(isolate);
@@ -1915,8 +1929,9 @@
v8::TryCatch::~TryCatch() {
ASSERT(isolate_ == i::Isolate::Current());
if (rethrow_) {
- v8::HandleScope scope(reinterpret_cast<Isolate*>(isolate_));
- v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(Exception());
+ v8::Isolate* isolate = reinterpret_cast<Isolate*>(isolate_);
+ v8::HandleScope scope(isolate);
+ v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(isolate, Exception());
if (HasCaught() && capture_message_) {
// If an exception was caught and rethrow_ is indicated, the saved
// message, script, and location need to be restored to Isolate TLS
@@ -1926,7 +1941,7 @@
isolate_->RestorePendingMessageFromTryCatch(this);
}
isolate_->UnregisterTryCatchHandler(this);
- v8::ThrowException(exc);
+ reinterpret_cast<Isolate*>(isolate_)->ThrowException(exc);
ASSERT(!isolate_->thread_local_top()->rethrowing_message_);
} else {
isolate_->UnregisterTryCatchHandler(this);
@@ -1952,7 +1967,7 @@
v8::Handle<v8::Value> v8::TryCatch::ReThrow() {
if (!HasCaught()) return v8::Local<v8::Value>();
rethrow_ = true;
- return v8::Undefined();
+ return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate_));
}
@@ -4122,10 +4137,12 @@
Handle<Value> Function::GetScriptId() const {
i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
- if (!func->shared()->script()->IsScript())
- return v8::Undefined();
+ i::Isolate* isolate = func->GetIsolate();
+ if (!func->shared()->script()->IsScript()) {
+ return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
+ }
i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
- return Utils::ToLocal(i::Handle<i::Object>(script->id(), func->GetIsolate()));
+ return Utils::ToLocal(i::Handle<i::Object>(script->id(), isolate));
}
@@ -6361,6 +6378,20 @@
}
+v8::Local<Value> Isolate::ThrowException(v8::Local<v8::Value> value) {
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
+ ENTER_V8(isolate);
+ // If we're passed an empty handle, we throw an undefined exception
+ // to deal more gracefully with out of memory situations.
+ if (value.IsEmpty()) {
+ isolate->ScheduleThrow(isolate->heap()->undefined_value());
+ } else {
+ isolate->ScheduleThrow(*Utils::OpenHandle(*value));
+ }
+ return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
+}
+
+
void Isolate::SetObjectGroupId(const Persistent<Value>& object,
UniqueId id) {
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this);
@@ -7108,7 +7139,7 @@
isolate->factory()->NewNumberFromInt(edge->index()));
default: UNREACHABLE();
}
- return v8::Undefined();
+ return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
}
diff --git a/src/arguments.h b/src/arguments.h
index f291816..634545e 100644
--- a/src/arguments.h
+++ b/src/arguments.h
@@ -238,6 +238,12 @@
typedef CustomArguments<T> Super;
static const int kArgsLength = T::kArgsLength;
static const int kHolderIndex = T::kHolderIndex;
+ static const int kDataIndex = T::kDataIndex;
+ static const int kReturnValueDefaultValueIndex =
+ T::kReturnValueDefaultValueIndex;
+ static const int kIsolateIndex = T::kIsolateIndex;
+ static const int kCalleeIndex = T::kCalleeIndex;
+ static const int kContextSaveIndex = T::kContextSaveIndex;
FunctionCallbackArguments(internal::Isolate* isolate,
internal::Object* data,
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index 6308b34..b860e3e 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -842,27 +842,25 @@
int argc,
bool restore_context) {
// ----------- S t a t e -------------
- // -- sp[0] : context
- // -- sp[4] : holder (set by CheckPrototypes)
- // -- sp[8] : callee JS function
- // -- sp[12] : call data
- // -- sp[16] : isolate
- // -- sp[20] : ReturnValue default value
- // -- sp[24] : ReturnValue
+ // -- sp[0] - sp[24] : FunctionCallbackInfo, incl.
+ // : holder (set by CheckPrototypes)
// -- sp[28] : last JS argument
// -- ...
// -- sp[(argc + 6) * 4] : first JS argument
// -- sp[(argc + 7) * 4] : receiver
// -----------------------------------
+ typedef FunctionCallbackArguments FCA;
+ const int kArgs = kFastApiCallArguments;
// Save calling context.
- __ str(cp, MemOperand(sp));
+ __ str(cp,
+ MemOperand(sp, (kArgs - 1 + FCA::kContextSaveIndex) * kPointerSize));
// Get the function and setup the context.
Handle<JSFunction> function = optimization.constant_function();
__ LoadHeapObject(r5, function);
__ ldr(cp, FieldMemOperand(r5, JSFunction::kContextOffset));
- __ str(r5, MemOperand(sp, 2 * kPointerSize));
+ __ str(r5, MemOperand(sp, (kArgs - 1 + FCA::kCalleeIndex) * kPointerSize));
- // Pass the additional arguments.
+ // Construct the FunctionCallbackInfo.
Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
Handle<Object> call_data(api_call_info->data(), masm->isolate());
if (masm->isolate()->heap()->InNewSpace(*call_data)) {
@@ -872,17 +870,21 @@
__ Move(r6, call_data);
}
// Store call data.
- __ str(r6, MemOperand(sp, 3 * kPointerSize));
+ __ str(r6, MemOperand(sp, (kArgs - 1 + FCA::kDataIndex) * kPointerSize));
// Store isolate.
__ mov(r5, Operand(ExternalReference::isolate_address(masm->isolate())));
- __ str(r5, MemOperand(sp, 4 * kPointerSize));
+ __ str(r5, MemOperand(sp, (kArgs - 1 + FCA::kIsolateIndex) * kPointerSize));
// Store ReturnValue default and ReturnValue.
__ LoadRoot(r5, Heap::kUndefinedValueRootIndex);
- __ str(r5, MemOperand(sp, 5 * kPointerSize));
- __ str(r5, MemOperand(sp, 6 * kPointerSize));
+ __ str(r5,
+ MemOperand(sp, (kArgs - 1 + FCA::kReturnValueOffset) * kPointerSize));
+ __ str(
+ r5,
+ MemOperand(
+ sp, (kArgs - 1 + FCA::kReturnValueDefaultValueIndex) * kPointerSize));
// Prepare arguments.
- __ add(r2, sp, Operand((kFastApiCallArguments - 1) * kPointerSize));
+ __ add(r2, sp, Operand((kArgs - 1) * kPointerSize));
// Allocate the v8::Arguments structure in the arguments' space since
// it's not controlled by GC.
@@ -906,7 +908,7 @@
__ mov(ip, Operand::Zero());
__ str(ip, MemOperand(r0, 3 * kPointerSize));
- const int kStackUnwindSpace = argc + kFastApiCallArguments + 1;
+ const int kStackUnwindSpace = argc + kArgs + 1;
Address function_address = v8::ToCData<Address>(api_call_info->callback());
ApiFunction fun(function_address);
ExternalReference::Type type = ExternalReference::DIRECT_API_CALL;
@@ -921,9 +923,9 @@
AllowExternalCallThatCantCauseGC scope(masm);
MemOperand context_restore_operand(
- fp, 2 * kPointerSize);
+ fp, (kArgs + 1 + FCA::kContextSaveIndex) * kPointerSize);
MemOperand return_value_operand(
- fp, (kFastApiCallArguments + 1) * kPointerSize);
+ fp, (kArgs + 1 + FCA::kReturnValueOffset) * kPointerSize);
__ CallApiFunctionAndReturn(ref,
function_address,
thunk_ref,
diff --git a/src/d8-posix.cc b/src/d8-posix.cc
index 424dbbb..81c15ae 100644
--- a/src/d8-posix.cc
+++ b/src/d8-posix.cc
@@ -245,7 +245,8 @@
if (args[3]->IsNumber()) {
*total_timeout = args[3]->Int32Value();
} else {
- ThrowException(String::New("system: Argument 4 must be a number"));
+ args.GetIsolate()->ThrowException(
+ String::New("system: Argument 4 must be a number"));
return false;
}
}
@@ -253,7 +254,8 @@
if (args[2]->IsNumber()) {
*read_timeout = args[2]->Int32Value();
} else {
- ThrowException(String::New("system: Argument 3 must be a number"));
+ args.GetIsolate()->ThrowException(
+ String::New("system: Argument 3 must be a number"));
return false;
}
}
@@ -456,7 +458,8 @@
Handle<Array> command_args;
if (args.Length() > 1) {
if (!args[1]->IsArray()) {
- ThrowException(String::New("system: Argument 2 must be an array"));
+ args.GetIsolate()->ThrowException(
+ String::New("system: Argument 2 must be an array"));
return;
}
command_args = Handle<Array>::Cast(args[1]);
@@ -464,11 +467,13 @@
command_args = Array::New(0);
}
if (command_args->Length() > ExecArgs::kMaxArgs) {
- ThrowException(String::New("Too many arguments to system()"));
+ args.GetIsolate()->ThrowException(
+ String::New("Too many arguments to system()"));
return;
}
if (args.Length() < 1) {
- ThrowException(String::New("Too few arguments to system()"));
+ args.GetIsolate()->ThrowException(
+ String::New("Too few arguments to system()"));
return;
}
@@ -483,11 +488,13 @@
int stdout_fds[2];
if (pipe(exec_error_fds) != 0) {
- ThrowException(String::New("pipe syscall failed."));
+ args.GetIsolate()->ThrowException(
+ String::New("pipe syscall failed."));
return;
}
if (pipe(stdout_fds) != 0) {
- ThrowException(String::New("pipe syscall failed."));
+ args.GetIsolate()->ThrowException(
+ String::New("pipe syscall failed."));
return;
}
@@ -531,17 +538,17 @@
void Shell::ChangeDirectory(const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() != 1) {
const char* message = "chdir() takes one argument";
- ThrowException(String::New(message));
+ args.GetIsolate()->ThrowException(String::New(message));
return;
}
String::Utf8Value directory(args[0]);
if (*directory == NULL) {
const char* message = "os.chdir(): String conversion of argument failed.";
- ThrowException(String::New(message));
+ args.GetIsolate()->ThrowException(String::New(message));
return;
}
if (chdir(*directory) != 0) {
- ThrowException(String::New(strerror(errno)));
+ args.GetIsolate()->ThrowException(String::New(strerror(errno)));
return;
}
}
@@ -550,7 +557,7 @@
void Shell::SetUMask(const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() != 1) {
const char* message = "umask() takes one argument";
- ThrowException(String::New(message));
+ args.GetIsolate()->ThrowException(String::New(message));
return;
}
if (args[0]->IsNumber()) {
@@ -560,7 +567,7 @@
return;
} else {
const char* message = "umask() argument must be numeric";
- ThrowException(String::New(message));
+ args.GetIsolate()->ThrowException(String::New(message));
return;
}
}
@@ -616,18 +623,18 @@
mask = args[1]->Int32Value();
} else {
const char* message = "mkdirp() second argument must be numeric";
- ThrowException(String::New(message));
+ args.GetIsolate()->ThrowException(String::New(message));
return;
}
} else if (args.Length() != 1) {
const char* message = "mkdirp() takes one or two arguments";
- ThrowException(String::New(message));
+ args.GetIsolate()->ThrowException(String::New(message));
return;
}
String::Utf8Value directory(args[0]);
if (*directory == NULL) {
const char* message = "os.mkdirp(): String conversion of argument failed.";
- ThrowException(String::New(message));
+ args.GetIsolate()->ThrowException(String::New(message));
return;
}
mkdirp(*directory, mask);
@@ -637,13 +644,13 @@
void Shell::RemoveDirectory(const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() != 1) {
const char* message = "rmdir() takes one or two arguments";
- ThrowException(String::New(message));
+ args.GetIsolate()->ThrowException(String::New(message));
return;
}
String::Utf8Value directory(args[0]);
if (*directory == NULL) {
const char* message = "os.rmdir(): String conversion of argument failed.";
- ThrowException(String::New(message));
+ args.GetIsolate()->ThrowException(String::New(message));
return;
}
rmdir(*directory);
@@ -653,7 +660,7 @@
void Shell::SetEnvironment(const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() != 2) {
const char* message = "setenv() takes two arguments";
- ThrowException(String::New(message));
+ args.GetIsolate()->ThrowException(String::New(message));
return;
}
String::Utf8Value var(args[0]);
@@ -661,13 +668,13 @@
if (*var == NULL) {
const char* message =
"os.setenv(): String conversion of variable name failed.";
- ThrowException(String::New(message));
+ args.GetIsolate()->ThrowException(String::New(message));
return;
}
if (*value == NULL) {
const char* message =
"os.setenv(): String conversion of variable contents failed.";
- ThrowException(String::New(message));
+ args.GetIsolate()->ThrowException(String::New(message));
return;
}
setenv(*var, *value, 1);
@@ -677,14 +684,14 @@
void Shell::UnsetEnvironment(const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() != 1) {
const char* message = "unsetenv() takes one argument";
- ThrowException(String::New(message));
+ args.GetIsolate()->ThrowException(String::New(message));
return;
}
String::Utf8Value var(args[0]);
if (*var == NULL) {
const char* message =
"os.setenv(): String conversion of variable name failed.";
- ThrowException(String::New(message));
+ args.GetIsolate()->ThrowException(String::New(message));
return;
}
unsetenv(*var);
diff --git a/src/d8.cc b/src/d8.cc
index 614b16e..1c6e453 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -49,6 +49,7 @@
#endif // !V8_SHARED
#ifdef V8_SHARED
+#include "../include/v8-defaults.h"
#include "../include/v8-testing.h"
#endif // V8_SHARED
@@ -66,6 +67,7 @@
#include "natives.h"
#include "platform.h"
#include "v8.h"
+#include "v8-defaults.h"
#endif // V8_SHARED
#if !defined(_WIN32) && !defined(_WIN64)
@@ -1649,6 +1651,7 @@
#else
SetStandaloneFlagsViaCommandLine();
#endif
+ v8::SetDefaultResourceConstraintsForCurrentPlatform();
ShellArrayBufferAllocator array_buffer_allocator;
v8::V8::SetArrayBufferAllocator(&array_buffer_allocator);
int result = 0;
diff --git a/src/debug.cc b/src/debug.cc
index 63d33eb..c820b97 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -3135,8 +3135,7 @@
v8::Local<v8::Function> fun =
v8::Local<v8::Function>::Cast(api_exec_state->Get(fun_name));
- v8::Handle<v8::Boolean> running =
- auto_continue ? v8::True() : v8::False();
+ v8::Handle<v8::Boolean> running = v8::Boolean::New(auto_continue);
static const int kArgc = 1;
v8::Handle<Value> argv[kArgc] = { running };
cmd_processor = v8::Local<v8::Object>::Cast(
diff --git a/src/defaults.cc b/src/defaults.cc
new file mode 100644
index 0000000..301155f
--- /dev/null
+++ b/src/defaults.cc
@@ -0,0 +1,71 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "../include/v8-defaults.h"
+
+#include "platform.h"
+#include "globals.h"
+#include "v8.h"
+
+namespace v8 {
+
+bool ConfigureResourceConstraintsForCurrentPlatform(
+ ResourceConstraints* constraints) {
+ if (constraints == NULL) {
+ return false;
+ }
+
+ uint64_t physical_memory = i::OS::TotalPhysicalMemory();
+ int lump_of_memory = (i::kPointerSize / 4) * i::MB;
+
+ // The young_space_size should be a power of 2 and old_generation_size should
+ // be a multiple of Page::kPageSize.
+ if (physical_memory > 2ul * i::GB) {
+ constraints->set_max_young_space_size(16 * lump_of_memory);
+ constraints->set_max_old_space_size(700 * lump_of_memory);
+ constraints->set_max_executable_size(256 * lump_of_memory);
+ } else if (physical_memory > 512ul * i::MB) {
+ constraints->set_max_young_space_size(8 * lump_of_memory);
+ constraints->set_max_old_space_size(192 * lump_of_memory);
+ constraints->set_max_executable_size(192 * lump_of_memory);
+ } else /* (physical_memory <= 512GB) */ {
+ constraints->set_max_young_space_size(2 * lump_of_memory);
+ constraints->set_max_old_space_size(96 * lump_of_memory);
+ constraints->set_max_executable_size(96 * lump_of_memory);
+ }
+ return true;
+}
+
+
+bool SetDefaultResourceConstraintsForCurrentPlatform() {
+ ResourceConstraints constraints;
+ if (!ConfigureResourceConstraintsForCurrentPlatform(&constraints))
+ return false;
+ return SetResourceConstraints(&constraints);
+}
+
+} // namespace v8::internal
diff --git a/src/extensions/externalize-string-extension.cc b/src/extensions/externalize-string-extension.cc
index 5fd821b..9fdb194 100644
--- a/src/extensions/externalize-string-extension.cc
+++ b/src/extensions/externalize-string-extension.cc
@@ -75,7 +75,7 @@
void ExternalizeStringExtension::Externalize(
const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() < 1 || !args[0]->IsString()) {
- v8::ThrowException(v8::String::New(
+ args.GetIsolate()->ThrowException(v8::String::New(
"First parameter to externalizeString() must be a string."));
return;
}
@@ -84,7 +84,7 @@
if (args[1]->IsBoolean()) {
force_two_byte = args[1]->BooleanValue();
} else {
- v8::ThrowException(v8::String::New(
+ args.GetIsolate()->ThrowException(v8::String::New(
"Second parameter to externalizeString() must be a boolean."));
return;
}
@@ -92,7 +92,7 @@
bool result = false;
Handle<String> string = Utils::OpenHandle(*args[0].As<v8::String>());
if (string->IsExternalString()) {
- v8::ThrowException(v8::String::New(
+ args.GetIsolate()->ThrowException(v8::String::New(
"externalizeString() can't externalize twice."));
return;
}
@@ -120,7 +120,8 @@
if (!result) delete resource;
}
if (!result) {
- v8::ThrowException(v8::String::New("externalizeString() failed."));
+ args.GetIsolate()->ThrowException(
+ v8::String::New("externalizeString() failed."));
return;
}
}
@@ -129,7 +130,7 @@
void ExternalizeStringExtension::IsAscii(
const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() != 1 || !args[0]->IsString()) {
- v8::ThrowException(v8::String::New(
+ args.GetIsolate()->ThrowException(v8::String::New(
"isAsciiString() requires a single string argument."));
return;
}
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index e745471..2a3c7e0 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -216,6 +216,11 @@
DEFINE_implication(track_computed_fields, track_fields)
DEFINE_bool(smi_binop, true, "support smi representation in binary operations")
+// Flags for optimization types.
+DEFINE_bool(optimize_for_size, false,
+ "Enables optimizations which favor memory size over execution "
+ "speed.")
+
// Flags for data representation optimizations
DEFINE_bool(unbox_double_arrays, true, "automatically unbox arrays of doubles")
DEFINE_bool(string_slices, true, "use string slices")
@@ -227,7 +232,7 @@
DEFINE_bool(use_gvn, true, "use hydrogen global value numbering")
DEFINE_bool(use_canonicalizing, true, "use hydrogen instruction canonicalizing")
DEFINE_bool(use_inlining, true, "use function inlining")
-DEFINE_bool(use_escape_analysis, true, "use hydrogen escape analysis")
+DEFINE_bool(use_escape_analysis, false, "use hydrogen escape analysis")
DEFINE_bool(use_allocation_folding, true, "use allocation folding")
DEFINE_int(max_inlining_levels, 5, "maximum number of inlining levels")
DEFINE_int(max_inlined_source_size, 600,
@@ -242,6 +247,7 @@
true,
"crankshaft harvests type feedback from stub cache")
DEFINE_bool(hydrogen_stats, false, "print statistics for hydrogen")
+DEFINE_bool(trace_check_elimination, false, "trace check elimination phase")
DEFINE_bool(trace_hydrogen, false, "trace generated hydrogen to file")
DEFINE_string(trace_hydrogen_filter, "*", "hydrogen tracing filter")
DEFINE_bool(trace_hydrogen_stubs, false, "trace generated hydrogen for stubs")
@@ -284,6 +290,7 @@
DEFINE_bool(analyze_environment_liveness, true,
"analyze liveness of environment slots and zap dead values")
DEFINE_bool(load_elimination, false, "use load elimination")
+DEFINE_bool(check_elimination, false, "use check elimination")
DEFINE_bool(dead_code_elimination, true, "use dead code elimination")
DEFINE_bool(fold_constants, true, "use constant folding")
DEFINE_bool(trace_dead_code_elimination, false, "trace dead code elimination")
@@ -589,9 +596,6 @@
0,
"Fixed seed to use to hash property keys (0 means random)"
"(with snapshots this option cannot override the baked-in seed)")
-DEFINE_maybe_bool(force_memory_constrained,
- "force (if true) or prevent (if false) the runtime from treating "
- "the device as being memory constrained.")
// v8.cc
DEFINE_bool(preemption, false,
diff --git a/src/globals.h b/src/globals.h
index 1977e68..d06c6d7 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -248,10 +248,12 @@
const int kPointerSizeLog2 = 3;
const intptr_t kIntptrSignBit = V8_INT64_C(0x8000000000000000);
const uintptr_t kUintptrAllBitsSet = V8_UINT64_C(0xFFFFFFFFFFFFFFFF);
+const bool kIs64BitArch = true;
#else
const int kPointerSizeLog2 = 2;
const intptr_t kIntptrSignBit = 0x80000000;
const uintptr_t kUintptrAllBitsSet = 0xFFFFFFFFu;
+const bool kIs64BitArch = false;
#endif
const int kBitsPerByte = 8;
diff --git a/src/heap.cc b/src/heap.cc
index 7b9f0d5..5d75cb4 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -67,29 +67,14 @@
Heap::Heap()
: isolate_(NULL),
+ code_range_size_(kIs64BitArch ? 512 * MB : 0),
// semispace_size_ should be a power of 2 and old_generation_size_ should be
// a multiple of Page::kPageSize.
-#if V8_TARGET_ARCH_X64
-#define LUMP_OF_MEMORY (2 * MB)
- code_range_size_(512*MB),
-#else
-#define LUMP_OF_MEMORY MB
- code_range_size_(0),
-#endif
-#if defined(ANDROID) || V8_TARGET_ARCH_MIPS
- reserved_semispace_size_(4 * Max(LUMP_OF_MEMORY, Page::kPageSize)),
- max_semispace_size_(4 * Max(LUMP_OF_MEMORY, Page::kPageSize)),
+ reserved_semispace_size_(8 * (kPointerSize / 4) * MB),
+ max_semispace_size_(8 * (kPointerSize / 4) * MB),
initial_semispace_size_(Page::kPageSize),
- max_old_generation_size_(192*MB),
- max_executable_size_(max_old_generation_size_),
-#else
- reserved_semispace_size_(8 * Max(LUMP_OF_MEMORY, Page::kPageSize)),
- max_semispace_size_(8 * Max(LUMP_OF_MEMORY, Page::kPageSize)),
- initial_semispace_size_(Page::kPageSize),
- max_old_generation_size_(700ul * LUMP_OF_MEMORY),
- max_executable_size_(256l * LUMP_OF_MEMORY),
-#endif
-
+ max_old_generation_size_(700ul * (kPointerSize / 4) * MB),
+ max_executable_size_(256ul * (kPointerSize / 4) * MB),
// Variables set based on semispace_size_ and old_generation_size_ in
// ConfigureHeap (survived_since_last_expansion_, external_allocation_limit_)
// Will be 4 * reserved_semispace_size_ to ensure that young
@@ -170,6 +155,9 @@
max_semispace_size_ = reserved_semispace_size_ = V8_MAX_SEMISPACE_SIZE;
#endif
+ // Ensure old_generation_size_ is a multiple of kPageSize.
+ ASSERT(MB >= Page::kPageSize);
+
intptr_t max_virtual = OS::MaxVirtualMemory();
if (max_virtual > 0) {
@@ -5340,25 +5328,10 @@
}
-MaybeObject* Heap::AllocateRawFixedArray(int length) {
- if (length < 0 || length > FixedArray::kMaxLength) {
- return Failure::OutOfMemoryException(0xd);
- }
- ASSERT(length > 0);
- // Use the general function if we're forced to always allocate.
- if (always_allocate()) return AllocateFixedArray(length, TENURED);
- // Allocate the raw data for a fixed array.
- int size = FixedArray::SizeFor(length);
- return size <= Page::kMaxNonCodeHeapObjectSize
- ? new_space_.AllocateRaw(size)
- : lo_space_->AllocateRaw(size, NOT_EXECUTABLE);
-}
-
-
MaybeObject* Heap::CopyFixedArrayWithMap(FixedArray* src, Map* map) {
int len = src->length();
Object* obj;
- { MaybeObject* maybe_obj = AllocateRawFixedArray(len);
+ { MaybeObject* maybe_obj = AllocateRawFixedArray(len, NOT_TENURED);
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
if (InNewSpace(obj)) {
@@ -5409,22 +5382,20 @@
}
-MUST_USE_RESULT static MaybeObject* AllocateFixedArrayWithFiller(
- Heap* heap,
- int length,
- PretenureFlag pretenure,
- Object* filler) {
+MaybeObject* Heap::AllocateFixedArrayWithFiller(int length,
+ PretenureFlag pretenure,
+ Object* filler) {
ASSERT(length >= 0);
- ASSERT(heap->empty_fixed_array()->IsFixedArray());
- if (length == 0) return heap->empty_fixed_array();
+ ASSERT(empty_fixed_array()->IsFixedArray());
+ if (length == 0) return empty_fixed_array();
- ASSERT(!heap->InNewSpace(filler));
+ ASSERT(!InNewSpace(filler));
Object* result;
- { MaybeObject* maybe_result = heap->AllocateRawFixedArray(length, pretenure);
+ { MaybeObject* maybe_result = AllocateRawFixedArray(length, pretenure);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
- HeapObject::cast(result)->set_map_no_write_barrier(heap->fixed_array_map());
+ HeapObject::cast(result)->set_map_no_write_barrier(fixed_array_map());
FixedArray* array = FixedArray::cast(result);
array->set_length(length);
MemsetPointer(array->data_start(), filler, length);
@@ -5433,19 +5404,13 @@
MaybeObject* Heap::AllocateFixedArray(int length, PretenureFlag pretenure) {
- return AllocateFixedArrayWithFiller(this,
- length,
- pretenure,
- undefined_value());
+ return AllocateFixedArrayWithFiller(length, pretenure, undefined_value());
}
MaybeObject* Heap::AllocateFixedArrayWithHoles(int length,
PretenureFlag pretenure) {
- return AllocateFixedArrayWithFiller(this,
- length,
- pretenure,
- the_hole_value());
+ return AllocateFixedArrayWithFiller(length, pretenure, the_hole_value());
}
@@ -5453,7 +5418,7 @@
if (length == 0) return empty_fixed_array();
Object* obj;
- { MaybeObject* maybe_obj = AllocateRawFixedArray(length);
+ { MaybeObject* maybe_obj = AllocateRawFixedArray(length, NOT_TENURED);
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
diff --git a/src/heap.h b/src/heap.h
index e059434..d25c7c8 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -951,10 +951,6 @@
int length,
PretenureFlag pretenure = NOT_TENURED);
- MUST_USE_RESULT MaybeObject* AllocateRawFixedDoubleArray(
- int length,
- PretenureFlag pretenure);
-
// Allocates a fixed double array with uninitialized values. Returns
// Failure::RetryAfterGC(requested_bytes, space) if the allocation failed.
// Please note this does not perform a garbage collection.
@@ -1505,11 +1501,6 @@
inline intptr_t AdjustAmountOfExternalAllocatedMemory(
intptr_t change_in_bytes);
- // Allocate uninitialized fixed array.
- MUST_USE_RESULT MaybeObject* AllocateRawFixedArray(int length);
- MUST_USE_RESULT MaybeObject* AllocateRawFixedArray(int length,
- PretenureFlag pretenure);
-
// This is only needed for testing high promotion mode.
void SetNewSpaceHighPromotionModeActive(bool mode) {
new_space_high_promotion_mode_active_ = mode;
@@ -2083,6 +2074,18 @@
// Allocate an uninitialized object in the global property cell space.
MUST_USE_RESULT inline MaybeObject* AllocateRawPropertyCell();
+ // Allocate an uninitialized fixed array.
+ MUST_USE_RESULT MaybeObject* AllocateRawFixedArray(
+ int length, PretenureFlag pretenure);
+
+ // Allocate an uninitialized fixed double array.
+ MUST_USE_RESULT MaybeObject* AllocateRawFixedDoubleArray(
+ int length, PretenureFlag pretenure);
+
+ // Allocate an initialized fixed array with the given filler value.
+ MUST_USE_RESULT MaybeObject* AllocateFixedArrayWithFiller(
+ int length, PretenureFlag pretenure, Object* filler);
+
// Initializes a JSObject based on its map.
void InitializeJSObjectFromMap(JSObject* obj,
FixedArray* properties,
diff --git a/src/hydrogen-check-elimination.cc b/src/hydrogen-check-elimination.cc
new file mode 100644
index 0000000..f712a39
--- /dev/null
+++ b/src/hydrogen-check-elimination.cc
@@ -0,0 +1,357 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "hydrogen-check-elimination.h"
+#include "hydrogen-alias-analysis.h"
+
+namespace v8 {
+namespace internal {
+
+static const int kMaxTrackedObjects = 10;
+typedef UniqueSet<Map>* MapSet;
+
+// The main datastructure used during check elimination, which stores a
+// set of known maps for each object.
+class HCheckTable {
+ public:
+ explicit HCheckTable(Zone* zone) : zone_(zone) {
+ Kill();
+ redundant_ = 0;
+ narrowed_ = 0;
+ empty_ = 0;
+ removed_ = 0;
+ compares_true_ = 0;
+ compares_false_ = 0;
+ transitions_ = 0;
+ loads_ = 0;
+ }
+
+ void ReduceCheckMaps(HCheckMaps* instr) {
+ HValue* object = instr->value()->ActualValue();
+ int index = Find(object);
+ if (index >= 0) {
+ // entry found;
+ MapSet a = known_maps_[index];
+ MapSet i = instr->map_set().Copy(zone_);
+ if (a->IsSubset(i)) {
+ // The first check is more strict; the second is redundant.
+ if (checks_[index] != NULL) {
+ instr->DeleteAndReplaceWith(checks_[index]);
+ redundant_++;
+ } else {
+ instr->DeleteAndReplaceWith(instr->value());
+ removed_++;
+ }
+ return;
+ }
+ i = i->Intersect(a, zone_);
+ if (i->size() == 0) {
+ // Intersection is empty; probably megamorphic, which is likely to
+ // deopt anyway, so just leave things as they are.
+ empty_++;
+ } else {
+ // TODO(titzer): replace the first check with a more strict check.
+ narrowed_++;
+ }
+ } else {
+ // No entry; insert a new one.
+ Insert(object, instr, instr->map_set().Copy(zone_));
+ }
+ }
+
+ void ReduceCheckValue(HCheckValue* instr) {
+ // Canonicalize HCheckValues; they might have their values load-eliminated.
+ HValue* value = instr->Canonicalize();
+ if (value == NULL) {
+ instr->DeleteAndReplaceWith(instr->value());
+ removed_++;
+ } else if (value != instr) {
+ instr->DeleteAndReplaceWith(value);
+ redundant_++;
+ }
+ }
+
+ void ReduceLoadNamedField(HLoadNamedField* instr) {
+ // Reduce a load of the map field when it is known to be a constant.
+ if (!IsMapAccess(instr->access())) return;
+
+ HValue* object = instr->object()->ActualValue();
+ MapSet maps = FindMaps(object);
+ if (maps == NULL || maps->size() != 1) return; // Not a constant.
+
+ Unique<Map> map = maps->at(0);
+ HConstant* constant = HConstant::CreateAndInsertBefore(
+ instr->block()->graph()->zone(), map, true, instr);
+ instr->DeleteAndReplaceWith(constant);
+ loads_++;
+ }
+
+ void ReduceCheckMapValue(HCheckMapValue* instr) {
+ if (!instr->map()->IsConstant()) return; // Nothing to learn.
+
+ HValue* object = instr->value()->ActualValue();
+ // Match a HCheckMapValue(object, HConstant(map))
+ Unique<Map> map = MapConstant(instr->map());
+ MapSet maps = FindMaps(object);
+ if (maps != NULL) {
+ if (maps->Contains(map)) {
+ if (maps->size() == 1) {
+ // Object is known to have exactly this map.
+ instr->DeleteAndReplaceWith(NULL);
+ removed_++;
+ } else {
+ // Only one map survives the check.
+ maps->Clear();
+ maps->Add(map, zone_);
+ }
+ }
+ } else {
+ // No prior information.
+ Insert(object, map);
+ }
+ }
+
+ void ReduceStoreNamedField(HStoreNamedField* instr) {
+ HValue* object = instr->object()->ActualValue();
+ if (instr->has_transition()) {
+ // This store transitions the object to a new map.
+ Kill(object);
+ Insert(object, MapConstant(instr->transition()));
+ } else if (IsMapAccess(instr->access())) {
+ // This is a store directly to the map field of the object.
+ Kill(object);
+ if (!instr->value()->IsConstant()) return;
+ Insert(object, MapConstant(instr->value()));
+ } else if (instr->CheckGVNFlag(kChangesMaps)) {
+ // This store indirectly changes the map of the object.
+ Kill(instr->object());
+ UNREACHABLE();
+ }
+ }
+
+ void ReduceCompareMap(HCompareMap* instr) {
+ MapSet maps = FindMaps(instr->value()->ActualValue());
+ if (maps == NULL) return;
+ if (maps->Contains(instr->map())) {
+ // TODO(titzer): replace with goto true branch
+ if (maps->size() == 1) compares_true_++;
+ } else {
+ // TODO(titzer): replace with goto false branch
+ compares_false_++;
+ }
+ }
+
+ void ReduceTransitionElementsKind(HTransitionElementsKind* instr) {
+ MapSet maps = FindMaps(instr->object()->ActualValue());
+ // Can only learn more about an object that already has a known set of maps.
+ if (maps == NULL) return;
+ if (maps->Contains(instr->original_map())) {
+ // If the object has the original map, it will be transitioned.
+ maps->Remove(instr->original_map());
+ maps->Add(instr->transitioned_map(), zone_);
+ } else {
+ // Object does not have the given map, thus the transition is redundant.
+ instr->DeleteAndReplaceWith(instr->object());
+ transitions_++;
+ }
+ }
+
+ // Kill everything in the table.
+ void Kill() {
+ memset(objects_, 0, sizeof(objects_));
+ }
+
+ // Kill everything in the table that may alias {object}.
+ void Kill(HValue* object) {
+ for (int i = 0; i < kMaxTrackedObjects; i++) {
+ if (objects_[i] == NULL) continue;
+ if (aliasing_.MayAlias(objects_[i], object)) objects_[i] = NULL;
+ }
+ ASSERT(Find(object) < 0);
+ }
+
+ void Print() {
+ for (int i = 0; i < kMaxTrackedObjects; i++) {
+ if (objects_[i] == NULL) continue;
+ PrintF(" checkmaps-table @%d: object #%d ", i, objects_[i]->id());
+ if (checks_[i] != NULL) {
+ PrintF("check #%d ", checks_[i]->id());
+ }
+ MapSet list = known_maps_[i];
+ PrintF("%d maps { ", list->size());
+ for (int j = 0; j < list->size(); j++) {
+ if (j > 0) PrintF(", ");
+ PrintF("%" V8PRIxPTR, list->at(j).Hashcode());
+ }
+ PrintF(" }\n");
+ }
+ }
+
+ void PrintStats() {
+ if (redundant_ > 0) PrintF(" redundant = %2d\n", redundant_);
+ if (removed_ > 0) PrintF(" removed = %2d\n", removed_);
+ if (narrowed_ > 0) PrintF(" narrowed = %2d\n", narrowed_);
+ if (loads_ > 0) PrintF(" loads = %2d\n", loads_);
+ if (empty_ > 0) PrintF(" empty = %2d\n", empty_);
+ if (compares_true_ > 0) PrintF(" cmp_true = %2d\n", compares_true_);
+ if (compares_false_ > 0) PrintF(" cmp_false = %2d\n", compares_false_);
+ if (transitions_ > 0) PrintF(" transitions = %2d\n", transitions_);
+ }
+
+ private:
+ int Find(HValue* object) {
+ for (int i = 0; i < kMaxTrackedObjects; i++) {
+ if (objects_[i] == NULL) continue;
+ if (aliasing_.MustAlias(objects_[i], object)) return i;
+ }
+ return -1;
+ }
+
+ MapSet FindMaps(HValue* object) {
+ int index = Find(object);
+ return index < 0 ? NULL : known_maps_[index];
+ }
+
+ void Insert(HValue* object, Unique<Map> map) {
+ MapSet list = new(zone_) UniqueSet<Map>();
+ list->Add(map, zone_);
+ Insert(object, NULL, list);
+ }
+
+ void Insert(HValue* object, HCheckMaps* check, MapSet maps) {
+ for (int i = 0; i < kMaxTrackedObjects; i++) {
+ // TODO(titzer): drop old entries instead of disallowing new ones.
+ if (objects_[i] == NULL) {
+ objects_[i] = object;
+ checks_[i] = check;
+ known_maps_[i] = maps;
+ return;
+ }
+ }
+ }
+
+ bool IsMapAccess(HObjectAccess access) {
+ return access.IsInobject() && access.offset() == JSObject::kMapOffset;
+ }
+
+ Unique<Map> MapConstant(HValue* value) {
+ return Unique<Map>::cast(HConstant::cast(value)->GetUnique());
+ }
+
+ Zone* zone_;
+ HValue* objects_[kMaxTrackedObjects];
+ HValue* checks_[kMaxTrackedObjects];
+ MapSet known_maps_[kMaxTrackedObjects];
+ HAliasAnalyzer aliasing_;
+ int redundant_;
+ int removed_;
+ int narrowed_;
+ int loads_;
+ int empty_;
+ int compares_true_;
+ int compares_false_;
+ int transitions_;
+};
+
+
+void HCheckEliminationPhase::Run() {
+ for (int i = 0; i < graph()->blocks()->length(); i++) {
+ EliminateLocalChecks(graph()->blocks()->at(i));
+ }
+}
+
+
+// For code de-uglification.
+#define TRACE(x) if (FLAG_trace_check_elimination) PrintF x
+
+
+// Eliminate checks local to a block.
+void HCheckEliminationPhase::EliminateLocalChecks(HBasicBlock* block) {
+ HCheckTable table(zone());
+ TRACE(("-- check-elim B%d ------------------------------------------------\n",
+ block->block_id()));
+
+ for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
+ bool changed = false;
+ HInstruction* instr = it.Current();
+
+ switch (instr->opcode()) {
+ case HValue::kCheckMaps: {
+ table.ReduceCheckMaps(HCheckMaps::cast(instr));
+ changed = true;
+ break;
+ }
+ case HValue::kCheckValue: {
+ table.ReduceCheckValue(HCheckValue::cast(instr));
+ changed = true;
+ break;
+ }
+ case HValue::kLoadNamedField: {
+ table.ReduceLoadNamedField(HLoadNamedField::cast(instr));
+ changed = true;
+ break;
+ }
+ case HValue::kStoreNamedField: {
+ table.ReduceStoreNamedField(HStoreNamedField::cast(instr));
+ changed = true;
+ break;
+ }
+ case HValue::kCompareMap: {
+ table.ReduceCompareMap(HCompareMap::cast(instr));
+ changed = true;
+ break;
+ }
+ case HValue::kTransitionElementsKind: {
+ table.ReduceTransitionElementsKind(
+ HTransitionElementsKind::cast(instr));
+ changed = true;
+ break;
+ }
+ case HValue::kCheckMapValue: {
+ table.ReduceCheckMapValue(HCheckMapValue::cast(instr));
+ changed = true;
+ break;
+ }
+ default: {
+ // If the instruction changes maps uncontrollably, kill the whole town.
+ if (instr->CheckGVNFlag(kChangesMaps)) {
+ table.Kill();
+ changed = true;
+ }
+ }
+ // Improvements possible:
+ // - eliminate HCheckSmi and HCheckHeapObject
+ }
+
+ if (changed && FLAG_trace_check_elimination) table.Print();
+ }
+
+ if (FLAG_trace_check_elimination) table.PrintStats();
+}
+
+
+} } // namespace v8::internal
diff --git a/src/hydrogen-check-elimination.h b/src/hydrogen-check-elimination.h
new file mode 100644
index 0000000..fa01964
--- /dev/null
+++ b/src/hydrogen-check-elimination.h
@@ -0,0 +1,52 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_HYDROGEN_CHECK_ELIMINATION_H_
+#define V8_HYDROGEN_CHECK_ELIMINATION_H_
+
+#include "hydrogen.h"
+
+namespace v8 {
+namespace internal {
+
+
+// Remove CheckMaps instructions through flow- and branch-sensitive analysis.
+class HCheckEliminationPhase : public HPhase {
+ public:
+ explicit HCheckEliminationPhase(HGraph* graph)
+ : HPhase("H_Check Elimination", graph) { }
+
+ void Run();
+
+ private:
+ void EliminateLocalChecks(HBasicBlock* block);
+};
+
+
+} } // namespace v8::internal
+
+#endif // V8_HYDROGEN_CHECK_ELIMINATION_H_
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 6125ca2..a66b6ab 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -2341,18 +2341,27 @@
}
+static void ReplayEnvironmentNested(const ZoneList<HValue*>* values,
+ HCapturedObject* other) {
+ for (int i = 0; i < values->length(); ++i) {
+ HValue* value = values->at(i);
+ if (value->IsCapturedObject()) {
+ if (HCapturedObject::cast(value)->capture_id() == other->capture_id()) {
+ values->at(i) = other;
+ } else {
+ ReplayEnvironmentNested(HCapturedObject::cast(value)->values(), other);
+ }
+ }
+ }
+}
+
+
// Replay captured objects by replacing all captured objects with the
// same capture id in the current and all outer environments.
void HCapturedObject::ReplayEnvironment(HEnvironment* env) {
ASSERT(env != NULL);
while (env != NULL) {
- for (int i = 0; i < env->length(); ++i) {
- HValue* value = env->values()->at(i);
- if (value->IsCapturedObject() &&
- HCapturedObject::cast(value)->capture_id() == this->capture_id()) {
- env->SetValueAt(i, this);
- }
- }
+ ReplayEnvironmentNested(env->values(), this);
env = env->outer();
}
}
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index 3b6822d..97e1b0e 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -3287,6 +3287,17 @@
return new_constant;
}
+ static HConstant* CreateAndInsertBefore(Zone* zone,
+ Unique<Object> unique,
+ bool is_not_in_new_space,
+ HInstruction* instruction) {
+ HConstant* new_constant = new(zone) HConstant(unique,
+ Representation::Tagged(), HType::Tagged(), false, is_not_in_new_space,
+ false, false);
+ new_constant->InsertBefore(instruction);
+ return new_constant;
+ }
+
Handle<Object> handle(Isolate* isolate) {
if (object_.handle().is_null()) {
// Default arguments to is_not_in_new_space depend on this heap number
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index fe59b54..57ea173 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -36,6 +36,7 @@
#include "hydrogen-bce.h"
#include "hydrogen-bch.h"
#include "hydrogen-canonicalize.h"
+#include "hydrogen-check-elimination.h"
#include "hydrogen-dce.h"
#include "hydrogen-dehoist.h"
#include "hydrogen-deoptimizing-mark.h"
@@ -3122,9 +3123,8 @@
return false;
}
- // Remove dead code and phis
+ if (FLAG_check_elimination) Run<HCheckEliminationPhase>();
if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
-
if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>();
if (FLAG_load_elimination) Run<HLoadEliminationPhase>();
@@ -3162,12 +3162,8 @@
// Eliminate redundant stack checks on backwards branches.
Run<HStackCheckEliminationPhase>();
- if (FLAG_array_bounds_checks_elimination) {
- Run<HBoundsCheckEliminationPhase>();
- }
- if (FLAG_array_bounds_checks_hoisting) {
- Run<HBoundsCheckHoistingPhase>();
- }
+ if (FLAG_array_bounds_checks_elimination) Run<HBoundsCheckEliminationPhase>();
+ if (FLAG_array_bounds_checks_hoisting) Run<HBoundsCheckHoistingPhase>();
if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>();
if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index d339da9..eb26477 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -462,51 +462,48 @@
bool restore_context) {
// ----------- S t a t e -------------
// -- esp[0] : return address
- // -- esp[4] : context
- // -- esp[8] : object passing the type check
- // (last fast api call extra argument,
- // set by CheckPrototypes)
- // -- esp[12] : api function
- // (first fast api call extra argument)
- // -- esp[16] : api call data
- // -- esp[20] : isolate
- // -- esp[24] : ReturnValue default value
- // -- esp[28] : ReturnValue
+ // -- esp[4] - esp[28] : FunctionCallbackInfo, incl.
+ // : object passing the type check
+ // (set by CheckPrototypes)
// -- esp[32] : last argument
// -- ...
// -- esp[(argc + 7) * 4] : first argument
// -- esp[(argc + 8) * 4] : receiver
// -----------------------------------
+ typedef FunctionCallbackArguments FCA;
+ const int kArgs = kFastApiCallArguments;
// Save calling context.
- __ mov(Operand(esp, kPointerSize), esi);
+ __ mov(Operand(esp, (kArgs + FCA::kContextSaveIndex) * kPointerSize), esi);
// Get the function and setup the context.
Handle<JSFunction> function = optimization.constant_function();
__ LoadHeapObject(edi, function);
__ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
- // Pass the additional arguments.
- __ mov(Operand(esp, 3 * kPointerSize), edi);
+ // Construct the FunctionCallbackInfo.
+ __ mov(Operand(esp, (kArgs + FCA::kCalleeIndex) * kPointerSize), edi);
Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
Handle<Object> call_data(api_call_info->data(), masm->isolate());
if (masm->isolate()->heap()->InNewSpace(*call_data)) {
__ mov(ecx, api_call_info);
__ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset));
- __ mov(Operand(esp, 4 * kPointerSize), ebx);
+ __ mov(Operand(esp, (kArgs + FCA::kDataIndex) * kPointerSize), ebx);
} else {
- __ mov(Operand(esp, 4 * kPointerSize), Immediate(call_data));
+ __ mov(Operand(esp, (kArgs + FCA::kDataIndex) * kPointerSize),
+ Immediate(call_data));
}
- __ mov(Operand(esp, 5 * kPointerSize),
+ __ mov(Operand(esp, (kArgs + FCA::kIsolateIndex) * kPointerSize),
Immediate(reinterpret_cast<int>(masm->isolate())));
- __ mov(Operand(esp, 6 * kPointerSize),
+ __ mov(Operand(esp, (kArgs + FCA::kReturnValueOffset) * kPointerSize),
masm->isolate()->factory()->undefined_value());
- __ mov(Operand(esp, 7 * kPointerSize),
- masm->isolate()->factory()->undefined_value());
+ __ mov(
+ Operand(esp, (kArgs + FCA::kReturnValueDefaultValueIndex) * kPointerSize),
+ masm->isolate()->factory()->undefined_value());
// Prepare arguments.
- STATIC_ASSERT(kFastApiCallArguments == 7);
- __ lea(eax, Operand(esp, kFastApiCallArguments * kPointerSize));
+ STATIC_ASSERT(kArgs == 7);
+ __ lea(eax, Operand(esp, kArgs * kPointerSize));
// API function gets reference to the v8::Arguments. If CPU profiler
@@ -539,13 +536,14 @@
Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback);
- Operand context_restore_operand(ebp, 2 * kPointerSize);
+ Operand context_restore_operand(
+ ebp, (kArgs + 1 + FCA::kContextSaveIndex) * kPointerSize);
Operand return_value_operand(
- ebp, (kFastApiCallArguments + 1) * kPointerSize);
+ ebp, (kArgs + 1 + FCA::kReturnValueOffset) * kPointerSize);
__ CallApiFunctionAndReturn(function_address,
thunk_address,
ApiParameterOperand(1),
- argc + kFastApiCallArguments + 1,
+ argc + kArgs + 1,
return_value_operand,
restore_context ?
&context_restore_operand : NULL);
diff --git a/src/isolate.cc b/src/isolate.cc
index 5a80d3d..3e5d2b9 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -1792,10 +1792,6 @@
// TODO(bmeurer) Initialized lazily because it depends on flags; can
// be fixed once the default isolate cleanup is done.
random_number_generator_(NULL),
- // TODO(rmcilroy) Currently setting this based on
- // FLAG_force_memory_constrained in Isolate::Init; move to here when
- // isolate cleanup is done
- is_memory_constrained_(false),
has_fatal_error_(false),
use_crankshaft_(true),
initialized_from_snapshot_(false),
@@ -2157,8 +2153,6 @@
TRACE_ISOLATE(init);
stress_deopt_count_ = FLAG_deopt_every_n_times;
- if (FLAG_force_memory_constrained.has_value)
- is_memory_constrained_ = FLAG_force_memory_constrained.value;
has_fatal_error_ = false;
diff --git a/src/isolate.h b/src/isolate.h
index cfea075..420cf03 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -1132,13 +1132,6 @@
// Given an address occupied by a live code object, return that object.
Object* FindCodeObject(Address a);
- bool is_memory_constrained() const {
- return is_memory_constrained_;
- }
- void set_is_memory_constrained(bool value) {
- is_memory_constrained_ = value;
- }
-
private:
Isolate();
@@ -1311,7 +1304,6 @@
unibrow::Mapping<unibrow::Ecma262Canonicalize> interp_canonicalize_mapping_;
CodeStubInterfaceDescriptor* code_stub_interface_descriptors_;
RandomNumberGenerator* random_number_generator_;
- bool is_memory_constrained_;
// True if fatal error has been signaled for this isolate.
bool has_fatal_error_;
diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc
index e0cf1b6..7177c70 100644
--- a/src/mips/stub-cache-mips.cc
+++ b/src/mips/stub-cache-mips.cc
@@ -832,27 +832,25 @@
int argc,
bool restore_context) {
// ----------- S t a t e -------------
- // -- sp[0] : context
- // -- sp[4] : holder (set by CheckPrototypes)
- // -- sp[8] : callee JS function
- // -- sp[12] : call data
- // -- sp[16] : isolate
- // -- sp[20] : ReturnValue default value
- // -- sp[24] : ReturnValue
+ // -- sp[0] - sp[24] : FunctionCallbackInfo, incl.
+ // : holder (set by CheckPrototypes)
// -- sp[28] : last JS argument
// -- ...
// -- sp[(argc + 6) * 4] : first JS argument
// -- sp[(argc + 7) * 4] : receiver
// -----------------------------------
+ typedef FunctionCallbackArguments FCA;
+ const int kArgs = kFastApiCallArguments;
// Save calling context.
- __ sw(cp, MemOperand(sp));
+ __ sw(cp,
+ MemOperand(sp, (kArgs - 1 + FCA::kContextSaveIndex) * kPointerSize));
// Get the function and setup the context.
Handle<JSFunction> function = optimization.constant_function();
__ LoadHeapObject(t1, function);
__ lw(cp, FieldMemOperand(t1, JSFunction::kContextOffset));
- __ sw(t1, MemOperand(sp, 2 * kPointerSize));
+ __ sw(t1, MemOperand(sp, (kArgs - 1 + FCA::kCalleeIndex) * kPointerSize));
- // Pass the additional arguments.
+ // Construct the FunctionCallbackInfo.
Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
Handle<Object> call_data(api_call_info->data(), masm->isolate());
if (masm->isolate()->heap()->InNewSpace(*call_data)) {
@@ -862,17 +860,20 @@
__ li(t2, call_data);
}
// Store call data.
- __ sw(t2, MemOperand(sp, 3 * kPointerSize));
+ __ sw(t2, MemOperand(sp, (kArgs - 1 + FCA::kDataIndex) * kPointerSize));
// Store isolate.
__ li(t3, Operand(ExternalReference::isolate_address(masm->isolate())));
- __ sw(t3, MemOperand(sp, 4 * kPointerSize));
+ __ sw(t3, MemOperand(sp, (kArgs - 1 + FCA::kIsolateIndex) * kPointerSize));
// Store ReturnValue default and ReturnValue.
__ LoadRoot(t1, Heap::kUndefinedValueRootIndex);
- __ sw(t1, MemOperand(sp, 5 * kPointerSize));
- __ sw(t1, MemOperand(sp, 6 * kPointerSize));
+ __ sw(t1,
+ MemOperand(sp, (kArgs - 1 + FCA::kReturnValueOffset) * kPointerSize));
+ __ sw(t1,
+ MemOperand(sp,
+ (kArgs - 1 + FCA::kReturnValueDefaultValueIndex) * kPointerSize));
// Prepare arguments.
- __ Addu(a2, sp, Operand((kFastApiCallArguments - 1) * kPointerSize));
+ __ Addu(a2, sp, Operand((kArgs - 1) * kPointerSize));
// Allocate the v8::Arguments structure in the arguments' space since
// it's not controlled by GC.
@@ -896,7 +897,7 @@
// v8::Arguments::is_construct_call = 0
__ sw(zero_reg, MemOperand(a0, 3 * kPointerSize));
- const int kStackUnwindSpace = argc + kFastApiCallArguments + 1;
+ const int kStackUnwindSpace = argc + kArgs + 1;
Address function_address = v8::ToCData<Address>(api_call_info->callback());
ApiFunction fun(function_address);
ExternalReference::Type type = ExternalReference::DIRECT_API_CALL;
@@ -912,9 +913,9 @@
AllowExternalCallThatCantCauseGC scope(masm);
MemOperand context_restore_operand(
- fp, 2 * kPointerSize);
+ fp, (kArgs + 1 + FCA::kContextSaveIndex) * kPointerSize);
MemOperand return_value_operand(
- fp, (kFastApiCallArguments + 1) * kPointerSize);
+ fp, (kArgs + 1 + FCA::kReturnValueOffset) * kPointerSize);
__ CallApiFunctionAndReturn(ref,
function_address,
thunk_ref,
diff --git a/src/platform-posix.cc b/src/platform-posix.cc
index df15ee2..797557d 100644
--- a/src/platform-posix.cc
+++ b/src/platform-posix.cc
@@ -100,6 +100,48 @@
}
+uint64_t OS::TotalPhysicalMemory() {
+#if V8_OS_MACOSX
+ int mib[2];
+ mib[0] = CTL_HW;
+ mib[1] = HW_MEMSIZE;
+ int64_t size = 0;
+ size_t len = sizeof(size);
+ if (sysctl(mib, 2, &size, &len, NULL, 0) != 0) {
+ UNREACHABLE();
+ return 0;
+ }
+ return static_cast<uint64_t>(size);
+#elif V8_OS_FREEBSD
+ int pages, page_size;
+ size_t size = sizeof(pages);
+ sysctlbyname("vm.stats.vm.v_page_count", &pages, &size, NULL, 0);
+ sysctlbyname("vm.stats.vm.v_page_size", &page_size, &size, NULL, 0);
+ if (pages == -1 || page_size == -1) {
+ UNREACHABLE();
+ return 0;
+ }
+ return static_cast<uint64_t>(pages) * page_size;
+#elif V8_OS_CYGWIN
+ MEMORYSTATUS memory_info;
+ memory_info.dwLength = sizeof(memory_info);
+ if (!GlobalMemoryStatus(&memory_info)) {
+ UNREACHABLE();
+ return 0;
+ }
+ return static_cast<uint64_t>(memory_info.dwTotalPhys);
+#else
+ intptr_t pages = sysconf(_SC_PHYS_PAGES);
+ intptr_t page_size = sysconf(_SC_PAGESIZE);
+ if (pages == -1 || page_size == -1) {
+ UNREACHABLE();
+ return 0;
+ }
+ return static_cast<uint64_t>(pages) * page_size;
+#endif
+}
+
+
int OS::ActivationFrameAlignment() {
#if V8_TARGET_ARCH_ARM
// On EABI ARM targets this is required for fp correctness in the
diff --git a/src/platform-win32.cc b/src/platform-win32.cc
index 41a4f14..3283dfa 100644
--- a/src/platform-win32.cc
+++ b/src/platform-win32.cc
@@ -1271,6 +1271,18 @@
}
+uint64_t OS::TotalPhysicalMemory() {
+ MEMORYSTATUSEX memory_info;
+ memory_info.dwLength = sizeof(memory_info);
+ if (!GlobalMemoryStatusEx(&memory_info)) {
+ UNREACHABLE();
+ return 0;
+ }
+
+ return static_cast<uint64_t>(memory_info.ullTotalPhys);
+}
+
+
#else // __MINGW32__
void OS::LogSharedLibraryAddresses(Isolate* isolate) { }
void OS::SignalCodeMovingGC() { }
diff --git a/src/platform.h b/src/platform.h
index 527de16..8e524ae 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -302,6 +302,9 @@
// positions indicated by the members of the CpuFeature enum from globals.h
static uint64_t CpuFeaturesImpliedByPlatform();
+ // The total amount of physical memory available on the current system.
+ static uint64_t TotalPhysicalMemory();
+
// Maximum size of the virtual memory. 0 means there is no artificial
// limit.
static intptr_t MaxVirtualMemory();
diff --git a/src/runtime.cc b/src/runtime.cc
index f097681..38d1d8d 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -7952,21 +7952,18 @@
// Allocate the elements if needed.
if (length > 0) {
// Allocate the fixed array.
- Object* obj;
- { MaybeObject* maybe_obj = isolate->heap()->AllocateRawFixedArray(length);
- if (!maybe_obj->ToObject(&obj)) return maybe_obj;
+ FixedArray* array;
+ { MaybeObject* maybe_obj =
+ isolate->heap()->AllocateUninitializedFixedArray(length);
+ if (!maybe_obj->To(&array)) return maybe_obj;
}
DisallowHeapAllocation no_gc;
- FixedArray* array = reinterpret_cast<FixedArray*>(obj);
- array->set_map_no_write_barrier(isolate->heap()->fixed_array_map());
- array->set_length(length);
-
WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
for (int i = 0; i < length; i++) {
array->set(i, *--parameters, mode);
}
- JSObject::cast(result)->set_elements(FixedArray::cast(obj));
+ JSObject::cast(result)->set_elements(array);
}
return result;
}
diff --git a/src/unique.h b/src/unique.h
index fdb7016..a93b046 100644
--- a/src/unique.h
+++ b/src/unique.h
@@ -120,6 +120,10 @@
return handle_;
}
+ template <class S> static Unique<T> cast(Unique<S> that) {
+ return Unique<T>(that.raw_address_, Handle<T>::cast(that.handle_));
+ }
+
inline bool IsInitialized() const {
return raw_address_ != NULL || handle_.is_null();
}
@@ -169,6 +173,17 @@
array_[size_++] = uniq;
}
+ // Remove an element from this set. Mutates this set. O(|this|)
+ void Remove(Unique<T> uniq) {
+ for (int i = 0; i < size_; i++) {
+ if (array_[i] == uniq) {
+ while (++i < size_) array_[i - 1] = array_[i];
+ size_--;
+ return;
+ }
+ }
+ }
+
// Compare this set against another set. O(|this|).
bool Equals(UniqueSet<T>* that) const {
if (that->size_ != this->size_) return false;
@@ -273,6 +288,10 @@
return copy;
}
+ void Clear() {
+ size_ = 0;
+ }
+
inline int size() const {
return size_;
}
diff --git a/src/version.cc b/src/version.cc
index d4856ae..e310df0 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,8 +34,8 @@
// system so their names cannot be changed without changing the scripts.
#define MAJOR_VERSION 3
#define MINOR_VERSION 22
-#define BUILD_NUMBER 2
-#define PATCH_LEVEL 0
+#define BUILD_NUMBER 3
+#define PATCH_LEVEL 2
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
#define IS_CANDIDATE_VERSION 0
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index af8e55f..ef52cb4 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -447,49 +447,45 @@
bool restore_context) {
// ----------- S t a t e -------------
// -- rsp[0] : return address
- // -- rsp[8] : context save
- // -- rsp[16] : object passing the type check
- // (last fast api call extra argument,
- // set by CheckPrototypes)
- // -- rsp[24] : api function
- // (first fast api call extra argument)
- // -- rsp[32] : api call data
- // -- rsp[40] : isolate
- // -- rsp[48] : ReturnValue default value
- // -- rsp[56] : ReturnValue
- //
+ // -- rsp[8] - rsp[58] : FunctionCallbackInfo, incl.
+ // : object passing the type check
+ // (set by CheckPrototypes)
// -- rsp[64] : last argument
// -- ...
// -- rsp[(argc + 7) * 8] : first argument
// -- rsp[(argc + 8) * 8] : receiver
// -----------------------------------
- int api_call_argc = argc + kFastApiCallArguments;
- StackArgumentsAccessor args(rsp, api_call_argc);
+ typedef FunctionCallbackArguments FCA;
+ StackArgumentsAccessor args(rsp, argc + kFastApiCallArguments);
// Save calling context.
- __ movq(args.GetArgumentOperand(api_call_argc), rsi);
+ __ movq(args.GetArgumentOperand(argc + 1 - FCA::kContextSaveIndex), rsi);
// Get the function and setup the context.
Handle<JSFunction> function = optimization.constant_function();
__ LoadHeapObject(rdi, function);
__ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
- // Pass the additional arguments.
- __ movq(args.GetArgumentOperand(api_call_argc - 2), rdi);
+ // Construct the FunctionCallbackInfo on the stack.
+ __ movq(args.GetArgumentOperand(argc + 1 - FCA::kCalleeIndex), rdi);
Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
Handle<Object> call_data(api_call_info->data(), masm->isolate());
if (masm->isolate()->heap()->InNewSpace(*call_data)) {
__ Move(rcx, api_call_info);
__ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset));
- __ movq(args.GetArgumentOperand(api_call_argc - 3), rbx);
+ __ movq(args.GetArgumentOperand(argc + 1 - FCA::kDataIndex), rbx);
} else {
- __ Move(args.GetArgumentOperand(api_call_argc - 3), call_data);
+ __ Move(args.GetArgumentOperand(argc + 1 - FCA::kDataIndex), call_data);
}
__ movq(kScratchRegister,
ExternalReference::isolate_address(masm->isolate()));
- __ movq(args.GetArgumentOperand(api_call_argc - 4), kScratchRegister);
+ __ movq(args.GetArgumentOperand(argc + 1 - FCA::kIsolateIndex),
+ kScratchRegister);
__ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex);
- __ movq(args.GetArgumentOperand(api_call_argc - 5), kScratchRegister);
- __ movq(args.GetArgumentOperand(api_call_argc - 6), kScratchRegister);
+ __ movq(
+ args.GetArgumentOperand(argc + 1 - FCA::kReturnValueDefaultValueIndex),
+ kScratchRegister);
+ __ movq(args.GetArgumentOperand(argc + 1 - FCA::kReturnValueOffset),
+ kScratchRegister);
// Prepare arguments.
STATIC_ASSERT(kFastApiCallArguments == 7);
@@ -524,16 +520,18 @@
Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback);
- Operand context_restore_operand(rbp, 2 * kPointerSize);
+ Operand context_restore_operand(
+ rbp, (kFastApiCallArguments + 1 + FCA::kContextSaveIndex) * kPointerSize);
Operand return_value_operand(
- rbp, (kFastApiCallArguments + 1) * kPointerSize);
- __ CallApiFunctionAndReturn(function_address,
- thunk_address,
- callback_arg,
- api_call_argc + 1,
- return_value_operand,
- restore_context ?
- &context_restore_operand : NULL);
+ rbp,
+ (kFastApiCallArguments + 1 + FCA::kReturnValueOffset) * kPointerSize);
+ __ CallApiFunctionAndReturn(
+ function_address,
+ thunk_address,
+ callback_arg,
+ argc + kFastApiCallArguments + 1,
+ return_value_operand,
+ restore_context ? &context_restore_operand : NULL);
}
diff --git a/test/cctest/test-accessors.cc b/test/cctest/test-accessors.cc
index c3148ff..df4937e 100644
--- a/test/cctest/test-accessors.cc
+++ b/test/cctest/test-accessors.cc
@@ -354,7 +354,8 @@
THREADED_TEST(EmptyResult) {
LocalContext context;
- v8::HandleScope scope(context->GetIsolate());
+ v8::Isolate* isolate = context->GetIsolate();
+ v8::HandleScope scope(isolate);
v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
obj->SetAccessor(v8_str("xxx"), EmptyGetter, NULL, v8::String::New("data"));
v8::Handle<v8::Object> inst = obj->NewInstance();
@@ -362,7 +363,7 @@
Local<Script> scr = v8::Script::Compile(v8::String::New("obj.xxx"));
for (int i = 0; i < 10; i++) {
Local<Value> result = scr->Run();
- CHECK(result == v8::Undefined());
+ CHECK(result == v8::Undefined(isolate));
}
}
@@ -370,7 +371,8 @@
THREADED_TEST(NoReuseRegress) {
// Check that the IC generated for the one test doesn't get reused
// for the other.
- v8::HandleScope scope(CcTest::isolate());
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope scope(isolate);
{
v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
obj->SetAccessor(v8_str("xxx"), EmptyGetter, NULL, v8::String::New("data"));
@@ -380,7 +382,7 @@
Local<Script> scr = v8::Script::Compile(v8::String::New("obj.xxx"));
for (int i = 0; i < 2; i++) {
Local<Value> result = scr->Run();
- CHECK(result == v8::Undefined());
+ CHECK(result == v8::Undefined(isolate));
}
}
{
@@ -405,14 +407,14 @@
Local<String> name,
const v8::PropertyCallbackInfo<v8::Value>& info) {
ApiTestFuzzer::Fuzz();
- v8::ThrowException(v8_str("g"));
+ info.GetIsolate()->ThrowException(v8_str("g"));
}
static void ThrowingSetAccessor(Local<String> name,
Local<Value> value,
const v8::PropertyCallbackInfo<void>& info) {
- v8::ThrowException(value);
+ info.GetIsolate()->ThrowException(value);
}
@@ -505,7 +507,7 @@
static void AllocateHandles(Local<String> name,
const v8::PropertyCallbackInfo<v8::Value>& info) {
for (int i = 0; i < i::kHandleBlockSize + 1; i++) {
- v8::Local<v8::Value>::New(name);
+ v8::Local<v8::Value>::New(info.GetIsolate(), name);
}
info.GetReturnValue().Set(v8::Integer::New(100));
}
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index cfebeff..7a2f9de 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -204,7 +204,7 @@
CHECK(!local_env.IsEmpty());
local_env->Enter();
- v8::Handle<v8::Primitive> undef = v8::Undefined();
+ v8::Handle<v8::Primitive> undef = v8::Undefined(CcTest::isolate());
CHECK(!undef.IsEmpty());
CHECK(undef->IsUndefined());
@@ -391,8 +391,9 @@
THREADED_TEST(HulIgennem) {
LocalContext env;
- v8::HandleScope scope(env->GetIsolate());
- v8::Handle<v8::Primitive> undef = v8::Undefined();
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope scope(isolate);
+ v8::Handle<v8::Primitive> undef = v8::Undefined(isolate);
Local<String> undef_str = undef->ToString();
char* value = i::NewArray<char>(undef_str->Utf8Length() + 1);
undef_str->WriteUtf8(value);
@@ -403,7 +404,8 @@
THREADED_TEST(Access) {
LocalContext env;
- v8::HandleScope scope(env->GetIsolate());
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope scope(isolate);
Local<v8::Object> obj = v8::Object::New();
Local<Value> foo_before = obj->Get(v8_str("foo"));
CHECK(foo_before->IsUndefined());
@@ -1689,12 +1691,13 @@
THREADED_TEST(ToNumber) {
LocalContext env;
- v8::HandleScope scope(env->GetIsolate());
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope scope(isolate);
Local<String> str = v8_str("3.1415926");
CHECK_EQ(3.1415926, str->NumberValue());
- v8::Handle<v8::Boolean> t = v8::True();
+ v8::Handle<v8::Boolean> t = v8::True(isolate);
CHECK_EQ(1.0, t->NumberValue());
- v8::Handle<v8::Boolean> f = v8::False();
+ v8::Handle<v8::Boolean> f = v8::False(isolate);
CHECK_EQ(0.0, f->NumberValue());
}
@@ -1713,13 +1716,13 @@
THREADED_TEST(Boolean) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
- v8::Handle<v8::Boolean> t = v8::True();
+ v8::Handle<v8::Boolean> t = v8::True(CcTest::isolate());
CHECK(t->Value());
- v8::Handle<v8::Boolean> f = v8::False();
+ v8::Handle<v8::Boolean> f = v8::False(CcTest::isolate());
CHECK(!f->Value());
- v8::Handle<v8::Primitive> u = v8::Undefined();
+ v8::Handle<v8::Primitive> u = v8::Undefined(CcTest::isolate());
CHECK(!u->BooleanValue());
- v8::Handle<v8::Primitive> n = v8::Null();
+ v8::Handle<v8::Primitive> n = v8::Null(CcTest::isolate());
CHECK(!n->BooleanValue());
v8::Handle<String> str1 = v8_str("");
CHECK(!str1->BooleanValue());
@@ -2451,7 +2454,7 @@
Local<String> key,
const v8::PropertyCallbackInfo<v8::Value>& info) {
ApiTestFuzzer::Fuzz();
- info.GetReturnValue().Set(v8::ThrowException(key));
+ info.GetReturnValue().Set(info.GetIsolate()->ThrowException(key));
}
@@ -2459,7 +2462,7 @@
Local<String> key,
Local<Value>,
const v8::PropertyCallbackInfo<v8::Value>& info) {
- v8::ThrowException(key);
+ info.GetIsolate()->ThrowException(key);
info.GetReturnValue().SetUndefined(); // not the same as empty handle
}
@@ -3254,7 +3257,7 @@
THREADED_TEST(GlobalHandleUpcast) {
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
- v8::Local<String> local = v8::Local<String>::New(v8_str("str"));
+ v8::Local<String> local = v8::Local<String>::New(isolate, v8_str("str"));
v8::Persistent<String> global_string(isolate, local);
v8::Persistent<Value>& global_value =
v8::Persistent<Value>::Cast(global_string);
@@ -3304,10 +3307,8 @@
THREADED_TEST(LocalHandle) {
v8::HandleScope scope(CcTest::isolate());
- v8::Local<String> local = v8::Local<String>::New(v8_str("str"));
- CHECK_EQ(local->Length(), 3);
-
- local = v8::Local<String>::New(CcTest::isolate(), v8_str("str"));
+ v8::Local<String> local =
+ v8::Local<String>::New(CcTest::isolate(), v8_str("str"));
CHECK_EQ(local->Length(), 3);
}
@@ -3762,15 +3763,16 @@
TEST(MessageHandler3) {
message_received = false;
- v8::HandleScope scope(CcTest::isolate());
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope scope(isolate);
CHECK(!message_received);
v8::V8::AddMessageListener(check_message_3);
LocalContext context;
v8::ScriptOrigin origin =
v8::ScriptOrigin(v8_str("6.75"),
- v8::Integer::New(1),
- v8::Integer::New(2),
- v8::True());
+ v8::Integer::New(1, isolate),
+ v8::Integer::New(2, isolate),
+ v8::True(isolate));
v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
&origin);
script->Run();
@@ -3790,15 +3792,16 @@
TEST(MessageHandler4) {
message_received = false;
- v8::HandleScope scope(CcTest::isolate());
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope scope(isolate);
CHECK(!message_received);
v8::V8::AddMessageListener(check_message_4);
LocalContext context;
v8::ScriptOrigin origin =
v8::ScriptOrigin(v8_str("6.75"),
- v8::Integer::New(1),
- v8::Integer::New(2),
- v8::False());
+ v8::Integer::New(1, isolate),
+ v8::Integer::New(2, isolate),
+ v8::False(isolate));
v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
&origin);
script->Run();
@@ -3826,15 +3829,16 @@
TEST(MessageHandler5) {
message_received = false;
- v8::HandleScope scope(CcTest::isolate());
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope scope(isolate);
CHECK(!message_received);
v8::V8::AddMessageListener(check_message_5a);
LocalContext context;
v8::ScriptOrigin origin =
v8::ScriptOrigin(v8_str("6.75"),
- v8::Integer::New(1),
- v8::Integer::New(2),
- v8::True());
+ v8::Integer::New(1, isolate),
+ v8::Integer::New(2, isolate),
+ v8::True(isolate));
v8::Handle<v8::Script> script = Script::Compile(v8_str("throw 'error'"),
&origin);
script->Run();
@@ -3846,9 +3850,9 @@
v8::V8::AddMessageListener(check_message_5b);
origin =
v8::ScriptOrigin(v8_str("6.75"),
- v8::Integer::New(1),
- v8::Integer::New(2),
- v8::False());
+ v8::Integer::New(1, isolate),
+ v8::Integer::New(2, isolate),
+ v8::False(isolate));
script = Script::Compile(v8_str("throw 'error'"),
&origin);
script->Run();
@@ -4321,7 +4325,8 @@
THREADED_TEST(ConversionException) {
LocalContext env;
- v8::HandleScope scope(env->GetIsolate());
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope scope(isolate);
CompileRun(
"function TestClass() { };"
"TestClass.prototype.toString = function () { throw 'uncle?'; };"
@@ -4350,7 +4355,7 @@
CHECK(to_int32_result.IsEmpty());
CheckUncle(&try_catch);
- Local<Value> to_object_result = v8::Undefined()->ToObject();
+ Local<Value> to_object_result = v8::Undefined(isolate)->ToObject();
CHECK(to_object_result.IsEmpty());
CHECK(try_catch.HasCaught());
try_catch.Reset();
@@ -4375,7 +4380,7 @@
void ThrowFromC(const v8::FunctionCallbackInfo<v8::Value>& args) {
ApiTestFuzzer::Fuzz();
- v8::ThrowException(v8_str("konto"));
+ args.GetIsolate()->ThrowException(v8_str("konto"));
}
@@ -4658,7 +4663,7 @@
int count = args[0]->Int32Value();
int cInterval = args[2]->Int32Value();
if (count == 0) {
- v8::ThrowException(v8_str("FromC"));
+ args.GetIsolate()->ThrowException(v8_str("FromC"));
return;
} else {
Local<v8::Object> global =
@@ -4798,7 +4803,7 @@
void ThrowValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
ApiTestFuzzer::Fuzz();
CHECK_EQ(1, args.Length());
- v8::ThrowException(args[0]);
+ args.GetIsolate()->ThrowException(args[0]);
}
@@ -4896,7 +4901,7 @@
CHECK(try_catch.HasCaught());
try_catch.ReThrow();
} else {
- v8::ThrowException(v8_str("back"));
+ CcTest::isolate()->ThrowException(v8_str("back"));
}
}
@@ -4976,8 +4981,8 @@
CHECK(v8_num(0.0)->StrictEquals(v8_num(-0.0)));
Local<Value> not_a_number = v8_num(i::OS::nan_value());
CHECK(!not_a_number->StrictEquals(not_a_number));
- CHECK(v8::False()->StrictEquals(v8::False()));
- CHECK(!v8::False()->StrictEquals(v8::Undefined()));
+ CHECK(v8::False(isolate)->StrictEquals(v8::False(isolate)));
+ CHECK(!v8::False(isolate)->StrictEquals(v8::Undefined(isolate)));
v8::Handle<v8::Object> obj = v8::Object::New();
v8::Persistent<v8::Object> alias(isolate, obj);
@@ -4991,8 +4996,8 @@
CHECK(!v8_num(1)->SameValue(v8_num(2)));
CHECK(!v8_num(0.0)->SameValue(v8_num(-0.0)));
CHECK(not_a_number->SameValue(not_a_number));
- CHECK(v8::False()->SameValue(v8::False()));
- CHECK(!v8::False()->SameValue(v8::Undefined()));
+ CHECK(v8::False(isolate)->SameValue(v8::False(isolate)));
+ CHECK(!v8::False(isolate)->SameValue(v8::Undefined(isolate)));
}
@@ -6673,7 +6678,7 @@
static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message,
v8::Handle<Value> data) {
CHECK(message->GetScriptResourceName()->IsUndefined());
- CHECK_EQ(v8::Undefined(), message->GetScriptResourceName());
+ CHECK_EQ(v8::Undefined(CcTest::isolate()), message->GetScriptResourceName());
message->GetLineNumber();
message->GetSourceLine();
}
@@ -6910,12 +6915,13 @@
static void ArgumentsTestCallback(
const v8::FunctionCallbackInfo<v8::Value>& args) {
ApiTestFuzzer::Fuzz();
+ v8::Isolate* isolate = args.GetIsolate();
CHECK_EQ(args_fun, args.Callee());
CHECK_EQ(3, args.Length());
- CHECK_EQ(v8::Integer::New(1), args[0]);
- CHECK_EQ(v8::Integer::New(2), args[1]);
- CHECK_EQ(v8::Integer::New(3), args[2]);
- CHECK_EQ(v8::Undefined(), args[3]);
+ CHECK_EQ(v8::Integer::New(1, isolate), args[0]);
+ CHECK_EQ(v8::Integer::New(2, isolate), args[1]);
+ CHECK_EQ(v8::Integer::New(3, isolate), args[2]);
+ CHECK_EQ(v8::Undefined(isolate), args[3]);
v8::HandleScope scope(args.GetIsolate());
CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
}
@@ -7163,7 +7169,8 @@
THREADED_TEST(ObjectInstantiation) {
- v8::HandleScope scope(CcTest::isolate());
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope scope(isolate);
v8::Handle<v8::ObjectTemplate> templ = ObjectTemplate::New();
templ->SetAccessor(v8_str("t"), PGetter2);
LocalContext context;
@@ -7175,7 +7182,7 @@
context->Global()->Set(v8_str("o2"), obj);
v8::Handle<Value> value =
Script::Compile(v8_str("o.__proto__ === o2.__proto__"))->Run();
- CHECK_EQ(v8::True(), value);
+ CHECK_EQ(v8::True(isolate), value);
context->Global()->Set(v8_str("o"), obj);
}
}
@@ -9794,7 +9801,8 @@
THREADED_TEST(ConstructorForObject) {
LocalContext context;
- v8::HandleScope handle_scope(context->GetIsolate());
+ v8::Isolate* isolate = context->GetIsolate();
+ v8::HandleScope handle_scope(isolate);
{ Local<ObjectTemplate> instance_template = ObjectTemplate::New();
instance_template->SetCallAsFunctionHandler(ConstructorCallback);
@@ -9843,7 +9851,7 @@
CHECK(value->IsBoolean());
CHECK_EQ(true, value->BooleanValue());
- Handle<Value> args3[] = { v8::True() };
+ Handle<Value> args3[] = { v8::True(isolate) };
Local<Value> value_obj3 = instance->CallAsConstructor(1, args3);
CHECK(value_obj3->IsObject());
Local<Object> object3 = Local<Object>::Cast(value_obj3);
@@ -9853,7 +9861,7 @@
CHECK_EQ(true, value->BooleanValue());
// Call the Object's constructor with undefined.
- Handle<Value> args4[] = { v8::Undefined() };
+ Handle<Value> args4[] = { v8::Undefined(isolate) };
Local<Value> value_obj4 = instance->CallAsConstructor(1, args4);
CHECK(value_obj4->IsObject());
Local<Object> object4 = Local<Object>::Cast(value_obj4);
@@ -9862,7 +9870,7 @@
CHECK(value->IsUndefined());
// Call the Object's constructor with null.
- Handle<Value> args5[] = { v8::Null() };
+ Handle<Value> args5[] = { v8::Null(isolate) };
Local<Value> value_obj5 = instance->CallAsConstructor(1, args5);
CHECK(value_obj5->IsObject());
Local<Object> object5 = Local<Object>::Cast(value_obj5);
@@ -11259,7 +11267,7 @@
void ThrowingDirectApiCallback(
const v8::FunctionCallbackInfo<v8::Value>& args) {
- v8::ThrowException(v8_str("g"));
+ args.GetIsolate()->ThrowException(v8_str("g"));
}
@@ -11327,7 +11335,7 @@
void ThrowingDirectGetterCallback(
Local<String> name,
const v8::PropertyCallbackInfo<v8::Value>& info) {
- v8::ThrowException(v8_str("g"));
+ info.GetIsolate()->ThrowException(v8_str("g"));
}
@@ -11938,7 +11946,7 @@
info.GetReturnValue().Set(call_ic_function3);
}
if (interceptor_ic_exception_get_count == 20) {
- v8::ThrowException(v8_num(42));
+ info.GetIsolate()->ThrowException(v8_num(42));
return;
}
}
@@ -11983,7 +11991,7 @@
const v8::PropertyCallbackInfo<v8::Value>& info) {
ApiTestFuzzer::Fuzz();
if (++interceptor_ic_exception_set_count > 20) {
- v8::ThrowException(v8_num(42));
+ info.GetIsolate()->ThrowException(v8_num(42));
}
}
@@ -12055,7 +12063,7 @@
static void ThrowingGetter(Local<String> name,
const v8::PropertyCallbackInfo<v8::Value>& info) {
ApiTestFuzzer::Fuzz();
- ThrowException(Handle<Value>());
+ info.GetIsolate()->ThrowException(Handle<Value>());
info.GetReturnValue().SetUndefined();
}
@@ -12140,7 +12148,7 @@
static void ThrowViaApi(Handle<Message> message, Handle<Value> data) {
- if (--call_depth) ThrowException(v8_str("ThrowViaApi"));
+ if (--call_depth) CcTest::isolate()->ThrowException(v8_str("ThrowViaApi"));
}
@@ -12499,13 +12507,14 @@
static void ThrowInJS(const v8::FunctionCallbackInfo<v8::Value>& args) {
- CHECK(v8::Locker::IsLocked(CcTest::isolate()));
+ v8::Isolate* isolate = args.GetIsolate();
+ CHECK(v8::Locker::IsLocked(isolate));
ApiTestFuzzer::Fuzz();
- v8::Unlocker unlocker(CcTest::isolate());
+ v8::Unlocker unlocker(isolate);
const char* code = "throw 7;";
{
- v8::Locker nested_locker(CcTest::isolate());
- v8::HandleScope scope(args.GetIsolate());
+ v8::Locker nested_locker(isolate);
+ v8::HandleScope scope(isolate);
v8::Handle<Value> exception;
{ v8::TryCatch try_catch;
v8::Handle<Value> value = CompileRun(code);
@@ -12514,9 +12523,9 @@
// Make sure to wrap the exception in a new handle because
// the handle returned from the TryCatch is destroyed
// when the TryCatch is destroyed.
- exception = Local<Value>::New(try_catch.Exception());
+ exception = Local<Value>::New(isolate, try_catch.Exception());
}
- v8::ThrowException(exception);
+ args.GetIsolate()->ThrowException(exception);
}
}
@@ -13732,11 +13741,12 @@
THREADED_TEST(DisableAccessChecksWhileConfiguring) {
LocalContext context;
- v8::HandleScope scope(context->GetIsolate());
+ v8::Isolate* isolate = context->GetIsolate();
+ v8::HandleScope scope(isolate);
Local<ObjectTemplate> templ = ObjectTemplate::New();
templ->SetAccessCheckCallbacks(NamedSetAccessBlocker,
IndexedSetAccessBlocker);
- templ->Set(v8_str("x"), v8::True());
+ templ->Set(v8_str("x"), v8::True(isolate));
Local<v8::Object> instance = templ->NewInstance();
context->Global()->Set(v8_str("obj"), instance);
Local<Value> value = CompileRun("obj.x");
@@ -14153,14 +14163,14 @@
// Test LoadIC.
for (int i = 0; i < 2; i++) {
LocalContext context;
- context->Global()->Set(v8_str("tmp"), v8::True());
+ context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
context->Global()->Delete(v8_str("tmp"));
CompileRun("for (var j = 0; j < 10; j++) new RegExp('');");
}
// Test CallIC.
for (int i = 0; i < 2; i++) {
LocalContext context;
- context->Global()->Set(v8_str("tmp"), v8::True());
+ context->Global()->Set(v8_str("tmp"), v8::True(CcTest::isolate()));
context->Global()->Delete(v8_str("tmp"));
CompileRun("for (var j = 0; j < 10; j++) RegExp('')");
}
@@ -19394,20 +19404,20 @@
CHECK(result1->Equals(simple_object->GetPrototype()));
Local<Value> result2 = CompileRun("Object.getPrototypeOf(protected)");
- CHECK(result2->Equals(Undefined()));
+ CHECK(result2->Equals(Undefined(isolate)));
Local<Value> result3 = CompileRun("Object.getPrototypeOf(global)");
CHECK(result3->Equals(global_object->GetPrototype()));
Local<Value> result4 = CompileRun("Object.getPrototypeOf(proxy)");
- CHECK(result4->Equals(Undefined()));
+ CHECK(result4->Equals(Undefined(isolate)));
Local<Value> result5 = CompileRun("Object.getPrototypeOf(hidden)");
CHECK(result5->Equals(
object_with_hidden->GetPrototype()->ToObject()->GetPrototype()));
Local<Value> result6 = CompileRun("Object.getPrototypeOf(phidden)");
- CHECK(result6->Equals(Undefined()));
+ CHECK(result6->Equals(Undefined(isolate)));
}
@@ -19706,16 +19716,12 @@
v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);
i::Handle<i::Object> undefined_value = factory->undefined_value();
- CHECK(*v8::Utils::OpenHandle(*v8::Undefined()) == *undefined_value);
CHECK(*v8::Utils::OpenHandle(*v8::Undefined(isolate)) == *undefined_value);
i::Handle<i::Object> null_value = factory->null_value();
- CHECK(*v8::Utils::OpenHandle(*v8::Null()) == *null_value);
CHECK(*v8::Utils::OpenHandle(*v8::Null(isolate)) == *null_value);
i::Handle<i::Object> true_value = factory->true_value();
- CHECK(*v8::Utils::OpenHandle(*v8::True()) == *true_value);
CHECK(*v8::Utils::OpenHandle(*v8::True(isolate)) == *true_value);
i::Handle<i::Object> false_value = factory->false_value();
- CHECK(*v8::Utils::OpenHandle(*v8::False()) == *false_value);
CHECK(*v8::Utils::OpenHandle(*v8::False(isolate)) == *false_value);
}
@@ -20158,10 +20164,11 @@
THREADED_TEST(Regress2746) {
LocalContext context;
- v8::HandleScope scope(context->GetIsolate());
+ v8::Isolate* isolate = context->GetIsolate();
+ v8::HandleScope scope(isolate);
Local<Object> obj = Object::New();
Local<String> key = String::New("key");
- obj->SetHiddenValue(key, v8::Undefined());
+ obj->SetHiddenValue(key, v8::Undefined(isolate));
Local<Value> value = obj->GetHiddenValue(key);
CHECK(!value.IsEmpty());
CHECK(value->IsUndefined());
@@ -20341,7 +20348,8 @@
Local<v8::Value> data) {
access_check_fail_thrown = true;
i::PrintF("Access check failed. Error thrown.\n");
- v8::ThrowException(v8::Exception::Error(v8_str("cross context")));
+ CcTest::isolate()->ThrowException(
+ v8::Exception::Error(v8_str("cross context")));
}
@@ -20584,3 +20592,24 @@
CHECK_EQ(v8::Integer::New(17, isolate), result2);
}
+
+TEST(EscapeableHandleScope) {
+ HandleScope outer_scope(CcTest::isolate());
+ LocalContext context;
+ const int runs = 10;
+ Local<String> values[runs];
+ for (int i = 0; i < runs; i++) {
+ v8::EscapableHandleScope inner_scope(CcTest::isolate());
+ Local<String> value;
+ if (i != 0) value = v8_str("escape value");
+ values[i] = inner_scope.Escape(value);
+ }
+ for (int i = 0; i < runs; i++) {
+ Local<String> expected;
+ if (i != 0) {
+ CHECK_EQ(v8_str("escape value"), values[i]);
+ } else {
+ CHECK(values[i].IsEmpty());
+ }
+ }
+}
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index 8a3bfa4..df6d1f5 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -2400,7 +2400,8 @@
// the correct results.
TEST(DebugEvaluate) {
DebugLocalContext env;
- v8::HandleScope scope(env->GetIsolate());
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope scope(isolate);
env.ExposeDebug();
// Create a function for checking the evaluation when hitting a break point.
@@ -2413,13 +2414,13 @@
// Different expected vaules of x and a when in a break point (u = undefined,
// d = Hello, world!).
struct EvaluateCheck checks_uu[] = {
- {"x", v8::Undefined()},
- {"a", v8::Undefined()},
+ {"x", v8::Undefined(isolate)},
+ {"a", v8::Undefined(isolate)},
{NULL, v8::Handle<v8::Value>()}
};
struct EvaluateCheck checks_hu[] = {
{"x", v8::String::New("Hello, world!")},
- {"a", v8::Undefined()},
+ {"a", v8::Undefined(isolate)},
{NULL, v8::Handle<v8::Value>()}
};
struct EvaluateCheck checks_hh[] = {
@@ -2485,7 +2486,7 @@
// parameter.
checks = checks_uu;
v8::Handle<v8::Value> argv_bar_1[2] = {
- v8::Undefined(),
+ v8::Undefined(isolate),
v8::Number::New(barbar_break_position)
};
bar->Call(env->Global(), 2, argv_bar_1);
@@ -3105,7 +3106,8 @@
TEST(DebugStepIf) {
DebugLocalContext env;
- v8::HandleScope scope(env->GetIsolate());
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope scope(isolate);
// Register a debug event listener which steps and counts.
v8::Debug::SetDebugEventListener2(DebugEventStep);
@@ -3129,14 +3131,14 @@
// Stepping through the true part.
step_action = StepIn;
break_point_hit_count = 0;
- v8::Handle<v8::Value> argv_true[argc] = { v8::True() };
+ v8::Handle<v8::Value> argv_true[argc] = { v8::True(isolate) };
foo->Call(env->Global(), argc, argv_true);
CHECK_EQ(4, break_point_hit_count);
// Stepping through the false part.
step_action = StepIn;
break_point_hit_count = 0;
- v8::Handle<v8::Value> argv_false[argc] = { v8::False() };
+ v8::Handle<v8::Value> argv_false[argc] = { v8::False(isolate) };
foo->Call(env->Global(), argc, argv_false);
CHECK_EQ(5, break_point_hit_count);
@@ -3507,7 +3509,8 @@
TEST(DebugConditional) {
DebugLocalContext env;
- v8::HandleScope scope(env->GetIsolate());
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope scope(isolate);
// Register a debug event listener which steps and counts.
v8::Debug::SetDebugEventListener2(DebugEventStep);
@@ -3531,7 +3534,7 @@
step_action = StepIn;
break_point_hit_count = 0;
const int argc = 1;
- v8::Handle<v8::Value> argv_true[argc] = { v8::True() };
+ v8::Handle<v8::Value> argv_true[argc] = { v8::True(isolate) };
foo->Call(env->Global(), argc, argv_true);
CHECK_EQ(5, break_point_hit_count);
@@ -3759,7 +3762,8 @@
// Test that step in works with function.call.
TEST(DebugStepFunctionCall) {
DebugLocalContext env;
- v8::HandleScope scope(env->GetIsolate());
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope scope(isolate);
// Create a function for testing stepping.
v8::Local<v8::Function> foo = CompileFunction(
@@ -3786,7 +3790,7 @@
// Check stepping where the if condition in bar is true.
break_point_hit_count = 0;
const int argc = 1;
- v8::Handle<v8::Value> argv[argc] = { v8::True() };
+ v8::Handle<v8::Value> argv[argc] = { v8::True(isolate) };
foo->Call(env->Global(), argc, argv);
CHECK_EQ(8, break_point_hit_count);
diff --git a/test/cctest/test-decls.cc b/test/cctest/test-decls.cc
index e82c090..de27286 100644
--- a/test/cctest/test-decls.cc
+++ b/test/cctest/test-decls.cc
@@ -228,13 +228,14 @@
// about and doesn't handle.
TEST(Unknown) {
HandleScope scope(CcTest::isolate());
+ v8::V8::Initialize();
{ DeclarationContext context;
context.Check("var x; x",
1, // access
1, // declaration
2, // declaration + initialization
- EXPECT_RESULT, Undefined());
+ EXPECT_RESULT, Undefined(CcTest::isolate()));
}
{ DeclarationContext context;
@@ -258,15 +259,16 @@
1, // access
2, // declaration + initialization
1, // declaration
- EXPECT_RESULT, Undefined());
+ EXPECT_RESULT, Undefined(CcTest::isolate()));
}
{ DeclarationContext context;
+ // SB 0 - BUG 1213579
context.Check("const x = 0; x",
1, // access
2, // declaration + initialization
1, // declaration
- EXPECT_RESULT, Undefined()); // SB 0 - BUG 1213579
+ EXPECT_RESULT, Undefined(CcTest::isolate()));
}
}
@@ -313,7 +315,7 @@
1, // access
1, // initialization
1, // (re-)declaration
- EXPECT_RESULT, Undefined());
+ EXPECT_RESULT, Undefined(CcTest::isolate()));
}
{ PresentPropertyContext context;
@@ -336,14 +338,16 @@
TEST(Absent) {
- HandleScope scope(CcTest::isolate());
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::V8::Initialize();
+ HandleScope scope(isolate);
{ AbsentPropertyContext context;
context.Check("var x; x",
1, // access
1, // declaration
2, // declaration + initialization
- EXPECT_RESULT, Undefined());
+ EXPECT_RESULT, Undefined(isolate));
}
{ AbsentPropertyContext context;
@@ -367,7 +371,7 @@
1, // access
2, // declaration + initialization
1, // declaration
- EXPECT_RESULT, Undefined());
+ EXPECT_RESULT, Undefined(isolate));
}
{ AbsentPropertyContext context;
@@ -375,7 +379,7 @@
1, // access
2, // declaration + initialization
1, // declaration
- EXPECT_RESULT, Undefined()); // SB 0 - BUG 1213579
+ EXPECT_RESULT, Undefined(isolate)); // SB 0 - BUG 1213579
}
{ AbsentPropertyContext context;
@@ -383,7 +387,7 @@
1, // access
1, // declaration
1, // declaration + initialization
- EXPECT_RESULT, Undefined());
+ EXPECT_RESULT, Undefined(isolate));
}
}
@@ -426,6 +430,7 @@
TEST(Appearing) {
+ v8::V8::Initialize();
HandleScope scope(CcTest::isolate());
{ AppearingPropertyContext context;
@@ -433,7 +438,7 @@
1, // access
1, // declaration
2, // declaration + initialization
- EXPECT_RESULT, Undefined());
+ EXPECT_RESULT, Undefined(CcTest::isolate()));
}
{ AppearingPropertyContext context;
@@ -457,7 +462,7 @@
1, // access
2, // declaration + initialization
1, // declaration
- EXPECT_RESULT, Undefined());
+ EXPECT_RESULT, Undefined(CcTest::isolate()));
}
{ AppearingPropertyContext context;
@@ -465,7 +470,7 @@
1, // access
2, // declaration + initialization
1, // declaration
- EXPECT_RESULT, Undefined());
+ EXPECT_RESULT, Undefined(CcTest::isolate()));
// Result is undefined because declaration succeeded but
// initialization to 0 failed (due to context behavior).
}
@@ -518,6 +523,7 @@
TEST(Reappearing) {
+ v8::V8::Initialize();
HandleScope scope(CcTest::isolate());
{ ReappearingPropertyContext context;
@@ -525,7 +531,7 @@
0,
3, // const declaration+initialization, var initialization
3, // 2 x declaration + var initialization
- EXPECT_RESULT, Undefined());
+ EXPECT_RESULT, Undefined(CcTest::isolate()));
}
}
@@ -564,7 +570,7 @@
0,
0,
0,
- EXPECT_RESULT, Undefined());
+ EXPECT_RESULT, Undefined(CcTest::isolate()));
}
{ ExistsInPrototypeContext context;
@@ -580,7 +586,7 @@
0,
0,
0,
- EXPECT_RESULT, Undefined());
+ EXPECT_RESULT, Undefined(CcTest::isolate()));
}
{ ExistsInPrototypeContext context;
@@ -610,6 +616,7 @@
TEST(AbsentInPrototype) {
i::FLAG_es52_globals = true;
+ v8::V8::Initialize();
HandleScope scope(CcTest::isolate());
{ AbsentInPrototypeContext context;
@@ -617,7 +624,7 @@
0,
0,
0,
- EXPECT_RESULT, Undefined());
+ EXPECT_RESULT, Undefined(CcTest::isolate()));
}
}
@@ -689,7 +696,7 @@
0,
0,
1, // (re-)declaration
- EXPECT_RESULT, Undefined());
+ EXPECT_RESULT, Undefined(CcTest::isolate()));
}
// TODO(mstarzinger): The semantics of global const is vague.
diff --git a/test/cctest/test-object-observe.cc b/test/cctest/test-object-observe.cc
index 0c8e1cd..bf10295 100644
--- a/test/cctest/test-object-observe.cc
+++ b/test/cctest/test-object-observe.cc
@@ -394,7 +394,7 @@
{ obj, "updated", "foo", Number::New(75) }
};
EXPECT_RECORDS(CompileRun("records"), expected_records);
- obj->SetPrototype(Null());
+ obj->SetPrototype(Null(isolate.GetIsolate()));
CompileRun("obj.foo = 43");
const RecordExpectation expected_records2[] = {
{ obj, "new", "foo", Handle<Value>() }
diff --git a/test/cctest/test-unique.cc b/test/cctest/test-unique.cc
index 8a81dec..0936908 100644
--- a/test/cctest/test-unique.cc
+++ b/test/cctest/test-unique.cc
@@ -165,6 +165,46 @@
}
+TEST(UniqueSet_Remove) {
+ CcTest::InitializeVM();
+ MAKE_HANDLES_AND_DISALLOW_ALLOCATION;
+ MAKE_UNIQUES_A_B_C;
+
+ Zone zone(isolate);
+
+ UniqueSet<String>* set = new(&zone) UniqueSet<String>();
+
+ set->Add(A, &zone);
+ set->Add(B, &zone);
+ set->Add(C, &zone);
+ CHECK_EQ(3, set->size());
+
+ set->Remove(A);
+ CHECK_EQ(2, set->size());
+ CHECK(!set->Contains(A));
+ CHECK(set->Contains(B));
+ CHECK(set->Contains(C));
+
+ set->Remove(A);
+ CHECK_EQ(2, set->size());
+ CHECK(!set->Contains(A));
+ CHECK(set->Contains(B));
+ CHECK(set->Contains(C));
+
+ set->Remove(B);
+ CHECK_EQ(1, set->size());
+ CHECK(!set->Contains(A));
+ CHECK(!set->Contains(B));
+ CHECK(set->Contains(C));
+
+ set->Remove(C);
+ CHECK_EQ(0, set->size());
+ CHECK(!set->Contains(A));
+ CHECK(!set->Contains(B));
+ CHECK(!set->Contains(C));
+}
+
+
TEST(UniqueSet_Contains) {
CcTest::InitializeVM();
MAKE_HANDLES_AND_DISALLOW_ALLOCATION;
diff --git a/test/mjsunit/compiler/escape-analysis.js b/test/mjsunit/compiler/escape-analysis.js
index 74e638a..21ebcbb 100644
--- a/test/mjsunit/compiler/escape-analysis.js
+++ b/test/mjsunit/compiler/escape-analysis.js
@@ -271,3 +271,33 @@
%OptimizeFunctionOnNextCall(oob);
assertEquals(7, oob(cons2, true));
})();
+
+
+// Test non-shallow nested graph of captured objects.
+(function testDeep() {
+ var deopt = { deopt:false };
+ function constructor1() {
+ this.x = 23;
+ }
+ function constructor2(nested) {
+ this.a = 17;
+ this.b = nested;
+ this.c = 42;
+ }
+ function deep() {
+ var o1 = new constructor1();
+ var o2 = new constructor2(o1);
+ assertEquals(17, o2.a);
+ assertEquals(23, o2.b.x);
+ assertEquals(42, o2.c);
+ o1.x = 99;
+ deopt.deopt;
+ assertEquals(99, o1.x);
+ assertEquals(99, o2.b.x);
+ }
+ deep(); deep();
+ %OptimizeFunctionOnNextCall(deep);
+ deep(); deep();
+ delete deopt.deopt;
+ deep(); deep();
+})();
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index 1850c0e..94c79fb 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -270,6 +270,7 @@
'../../src/debug-agent.h',
'../../src/debug.cc',
'../../src/debug.h',
+ '../../src/defaults.cc',
'../../src/deoptimizer.cc',
'../../src/deoptimizer.h',
'../../src/disasm.h',
@@ -333,6 +334,8 @@
'../../src/hydrogen-bch.h',
'../../src/hydrogen-canonicalize.cc',
'../../src/hydrogen-canonicalize.h',
+ '../../src/hydrogen-check-elimination.cc',
+ '../../src/hydrogen-check-elimination.h',
'../../src/hydrogen-dce.cc',
'../../src/hydrogen-dce.h',
'../../src/hydrogen-dehoist.cc',