Version 3.24.15
Introduce an API mirroring the gc extension.
Performance and stability improvements on all platforms.
git-svn-id: http://v8.googlecode.com/svn/trunk@18575 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index 61dc8e3..2311051 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2014-01-14: Version 3.24.15
+
+ Introduce an API mirroring the gc extension.
+
+ Performance and stability improvements on all platforms.
+
+
2014-01-10: Version 3.24.14
ES6: Add Object.getOwnPropertySymbols (issue 3049).
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 71907be..fe15157 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -61,15 +61,11 @@
def _SkipTreeCheck(input_api, output_api):
"""Check the env var whether we want to skip tree check.
Only skip if src/version.cc has been updated."""
- print "skip tree check?", input_api.environ.get('PRESUBMIT_TREE_CHECK')
src_version = 'src/version.cc'
- def FilterFile(file):
- print "Changed file:", file.LocalPath()
- return file.LocalPath() == src_version
- if not input_api.AffectedSourceFiles(FilterFile):
+ FilterFile = lambda file: file.LocalPath() == src_version
+ if not input_api.AffectedSourceFiles(
+ lambda file: file.LocalPath() == src_version):
return False
- if input_api.environ.get('PRESUBMIT_TREE_CHECK') == 'skip':
- print "Skip tree check requested via environment variable."
return input_api.environ.get('PRESUBMIT_TREE_CHECK') == 'skip'
@@ -98,7 +94,6 @@
results.extend(input_api.canned_checks.CheckChangeHasDescription(
input_api, output_api))
if not _SkipTreeCheck(input_api, output_api):
- print "Checking if tree is open."
results.extend(input_api.canned_checks.CheckTreeIsOpen(
input_api, output_api,
json_url='http://v8-status.appspot.com/current?format=json'))
diff --git a/include/v8.h b/include/v8.h
index c56295a..d186752 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -945,16 +945,6 @@
/**
* Pre-compiles the specified script (context-independent).
*
- * \param input Pointer to UTF-8 script source code.
- * \param length Length of UTF-8 script source code.
- */
- static ScriptData* PreCompile(Isolate* isolate,
- const char* input,
- int length);
-
- /**
- * Pre-compiles the specified script (context-independent).
- *
* NOTE: Pre-compilation using this method cannot happen on another thread
* without using Lockers.
*
@@ -3903,7 +3893,8 @@
enum GCCallbackFlags {
kNoGCCallbackFlags = 0,
kGCCallbackFlagCompacted = 1 << 0,
- kGCCallbackFlagConstructRetainedObjectInfos = 1 << 1
+ kGCCallbackFlagConstructRetainedObjectInfos = 1 << 1,
+ kGCCallbackFlagForced = 1 << 2
};
typedef void (*GCPrologueCallback)(GCType type, GCCallbackFlags flags);
@@ -3973,6 +3964,15 @@
};
/**
+ * Types of garbage collections that can be requested via
+ * RequestGarbageCollectionForTesting.
+ */
+ enum GarbageCollectionType {
+ kFullGarbageCollection,
+ kMinorGarbageCollection
+ };
+
+ /**
* Creates a new isolate. Does not change the currently entered
* isolate.
*
@@ -4184,6 +4184,17 @@
*/
void ClearInterrupt();
+ /**
+ * Request garbage collection in this Isolate. It is only valid to call this
+ * function if --expose_gc was specified.
+ *
+ * This should only be used for testing purposes and not to enforce a garbage
+ * collection schedule. It has strong negative impact on the garbage
+ * collection performance. Use IdleNotification() or LowMemoryNotification()
+ * instead to influence the garbage collection schedule.
+ */
+ void RequestGarbageCollectionForTesting(GarbageCollectionType type);
+
private:
Isolate();
Isolate(const Isolate&);
diff --git a/src/api.cc b/src/api.cc
index db2045f..5ef6e59 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -121,9 +121,9 @@
#define API_ENTRY_CHECK(isolate, msg) \
do { \
if (v8::Locker::IsActive()) { \
- ApiCheck(isolate->thread_manager()->IsLockedByCurrentThread(), \
- msg, \
- "Entering the V8 API without proper locking in place"); \
+ Utils::ApiCheck(isolate->thread_manager()->IsLockedByCurrentThread(), \
+ msg, \
+ "Entering the V8 API without proper locking in place"); \
} \
} while (false)
@@ -143,15 +143,6 @@
}
-static FatalErrorCallback GetFatalErrorHandler() {
- i::Isolate* isolate = i::Isolate::Current();
- if (isolate->exception_behavior() == NULL) {
- isolate->set_exception_behavior(DefaultFatalErrorHandler);
- }
- return isolate->exception_behavior();
-}
-
-
void i::FatalProcessOutOfMemory(const char* location) {
i::V8::FatalProcessOutOfMemory(location, false);
}
@@ -221,21 +212,19 @@
// HeapIterator here without doing a special GC.
isolate->heap()->RecordStats(&heap_stats, false);
}
- isolate->SignalFatalError();
- FatalErrorCallback callback = GetFatalErrorHandler();
- const char* message = "Allocation failed - process out of memory";
- callback(location, message);
- // If the callback returns, we stop execution.
+ Utils::ApiCheck(false, location, "Allocation failed - process out of memory");
+ // If the fatal error handler returns, we stop execution.
FATAL("API fatal error handler returned after process out of memory");
}
-bool Utils::ReportApiFailure(const char* location, const char* message) {
- FatalErrorCallback callback = GetFatalErrorHandler();
- callback(location, message);
+void Utils::ReportApiFailure(const char* location, const char* message) {
i::Isolate* isolate = i::Isolate::Current();
+ FatalErrorCallback callback = isolate->exception_behavior() == NULL
+ ? DefaultFatalErrorHandler
+ : isolate->exception_behavior();
+ callback(location, message);
isolate->SignalFatalError();
- return false;
}
@@ -245,20 +234,6 @@
}
-static inline bool ApiCheck(bool condition,
- const char* location,
- const char* message) {
- return condition ? true : Utils::ReportApiFailure(location, message);
-}
-
-
-static bool ReportEmptyHandle(const char* location) {
- FatalErrorCallback callback = GetFatalErrorHandler();
- callback(location, "Reading from empty handle");
- return true;
-}
-
-
static inline bool IsExecutionTerminatingCheck(i::Isolate* isolate) {
if (!isolate->IsInitialized()) return false;
if (isolate->has_scheduled_exception()) {
@@ -269,16 +244,6 @@
}
-static inline bool EmptyCheck(const char* location, v8::Handle<v8::Data> obj) {
- return obj.IsEmpty() ? ReportEmptyHandle(location) : false;
-}
-
-
-static inline bool EmptyCheck(const char* location, const v8::Data* obj) {
- return (obj == 0) ? ReportEmptyHandle(location) : false;
-}
-
-
// --- S t a t i c s ---
@@ -295,11 +260,10 @@
static inline bool EnsureInitializedForIsolate(i::Isolate* isolate,
const char* location) {
- if (isolate != NULL) {
- if (isolate->IsInitialized()) return true;
- }
- ASSERT(isolate == i::Isolate::Current());
- return ApiCheck(InitializeHelper(isolate), location, "Error initializing V8");
+ return (isolate != NULL && isolate->IsInitialized()) ||
+ Utils::ApiCheck(InitializeHelper(isolate),
+ location,
+ "Error initializing V8");
}
@@ -519,11 +483,11 @@
ResourceConstraints::ResourceConstraints()
- : max_young_space_size_(0),
- max_old_space_size_(0),
- max_executable_size_(0),
- stack_limit_(NULL),
- max_available_threads_(0) { }
+ : max_young_space_size_(0),
+ max_old_space_size_(0),
+ max_executable_size_(0),
+ stack_limit_(NULL),
+ max_available_threads_(0) { }
void ResourceConstraints::ConfigureDefaults(uint64_t physical_memory,
uint32_t number_of_processors) {
@@ -688,9 +652,9 @@
i::Object** EscapableHandleScope::Escape(i::Object** escape_value) {
- ApiCheck(*escape_slot_ == isolate_->heap()->the_hole_value(),
- "EscapeableHandleScope::Escape",
- "Escape value set twice");
+ Utils::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;
@@ -714,27 +678,25 @@
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
i::Handle<i::Context> context = i::Handle<i::Context>::null();
ENTER_V8(isolate);
- if (!ApiCheck(isolate->handle_scope_implementer()->LeaveContext(context),
- "v8::Context::Exit()",
- "Cannot exit non-entered context")) {
+ i::HandleScopeImplementer* impl = isolate->handle_scope_implementer();
+ if (!Utils::ApiCheck(impl->LeaveContext(context),
+ "v8::Context::Exit()",
+ "Cannot exit non-entered context")) {
return;
}
- // Content of 'last_context' could be NULL.
- i::Context* last_context =
- isolate->handle_scope_implementer()->RestoreContext();
- isolate->set_context(last_context);
+ isolate->set_context(impl->RestoreContext());
}
static void* DecodeSmiToAligned(i::Object* value, const char* location) {
- ApiCheck(value->IsSmi(), location, "Not a Smi");
+ Utils::ApiCheck(value->IsSmi(), location, "Not a Smi");
return reinterpret_cast<void*>(value);
}
static i::Smi* EncodeAlignedAsSmi(void* value, const char* location) {
i::Smi* smi = reinterpret_cast<i::Smi*>(value);
- ApiCheck(smi->IsSmi(), location, "Pointer is not aligned");
+ Utils::ApiCheck(smi->IsSmi(), location, "Pointer is not aligned");
return smi;
}
@@ -745,13 +707,14 @@
const char* location) {
i::Handle<i::Context> env = Utils::OpenHandle(context);
bool ok =
- ApiCheck(env->IsNativeContext(), location, "Not a native context") &&
- ApiCheck(index >= 0, location, "Negative index");
+ Utils::ApiCheck(env->IsNativeContext(),
+ location,
+ "Not a native context") &&
+ Utils::ApiCheck(index >= 0, location, "Negative index");
if (!ok) return i::Handle<i::FixedArray>();
i::Handle<i::FixedArray> data(env->embedder_data());
if (index < data->length()) return data;
- if (!can_grow) {
- Utils::ReportApiFailure(location, "Index too large");
+ if (!Utils::ApiCheck(can_grow, location, "Index too large")) {
return i::Handle<i::FixedArray>();
}
int new_size = i::Max(index, data->length() << 1) + 1;
@@ -899,9 +862,9 @@
const int kSize = 3;
v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
v8::Handle<v8::Data> data[kSize] = {
- name,
- value,
- v8::Integer::New(v8_isolate, attribute)};
+ name,
+ value,
+ v8::Integer::New(v8_isolate, attribute)};
TemplateSet(isolate, this, kSize, data);
}
@@ -920,18 +883,18 @@
const int kSize = 5;
v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
v8::Handle<v8::Data> data[kSize] = {
- name,
- getter,
- setter,
- v8::Integer::New(v8_isolate, attribute),
- v8::Integer::New(v8_isolate, access_control)};
+ name,
+ getter,
+ setter,
+ v8::Integer::New(v8_isolate, attribute),
+ v8::Integer::New(v8_isolate, access_control)};
TemplateSet(isolate, this, kSize, data);
}
// --- F u n c t i o n T e m p l a t e ---
static void InitializeFunctionTemplate(
- i::Handle<i::FunctionTemplateInfo> info) {
+ i::Handle<i::FunctionTemplateInfo> info) {
info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE));
info->set_flag(0);
}
@@ -1031,8 +994,8 @@
Local<AccessorSignature> AccessorSignature::New(
- Isolate* isolate,
- Handle<FunctionTemplate> receiver) {
+ Isolate* isolate,
+ Handle<FunctionTemplate> receiver) {
return Utils::AccessorSignatureToLocal(Utils::OpenHandle(*receiver));
}
@@ -1047,7 +1010,7 @@
i::Handle<i::DeclaredAccessorDescriptor>();
if (previous_descriptor != NULL) {
previous = Utils::OpenHandle(
- static_cast<DeclaredAccessorDescriptor*>(previous_descriptor));
+ static_cast<DeclaredAccessorDescriptor*>(previous_descriptor));
}
i::Handle<i::DeclaredAccessorDescriptor> descriptor =
i::DeclaredAccessorDescriptor::Create(internal_isolate, data, previous);
@@ -1056,7 +1019,7 @@
Local<RawOperationDescriptor>
- ObjectOperationDescriptor::NewInternalFieldDereference(
+ObjectOperationDescriptor::NewInternalFieldDereference(
Isolate* isolate,
int internal_field) {
i::DeclaredAccessorDescriptorData data;
@@ -1191,9 +1154,9 @@
}
-#define SET_FIELD_WRAPPED(obj, setter, cdata) do { \
- i::Handle<i::Object> foreign = FromCData(obj->GetIsolate(), cdata); \
- (obj)->setter(*foreign); \
+#define SET_FIELD_WRAPPED(obj, setter, cdata) do { \
+ i::Handle<i::Object> foreign = FromCData(obj->GetIsolate(), cdata); \
+ (obj)->setter(*foreign); \
} while (false)
@@ -1235,13 +1198,13 @@
template<typename Getter, typename Setter>
static i::Handle<i::AccessorInfo> MakeAccessorInfo(
- v8::Handle<String> name,
- Getter getter,
- Setter setter,
- v8::Handle<Value> data,
- v8::AccessControl settings,
- v8::PropertyAttribute attributes,
- v8::Handle<AccessorSignature> signature) {
+ v8::Handle<String> name,
+ Getter getter,
+ Setter setter,
+ v8::Handle<Value> data,
+ v8::AccessControl settings,
+ v8::PropertyAttribute attributes,
+ v8::Handle<AccessorSignature> signature) {
i::Isolate* isolate = Utils::OpenHandle(*name)->GetIsolate();
i::Handle<i::ExecutableAccessorInfo> obj =
isolate->factory()->NewExecutableAccessorInfo();
@@ -1256,13 +1219,13 @@
static i::Handle<i::AccessorInfo> MakeAccessorInfo(
- v8::Handle<String> name,
- v8::Handle<v8::DeclaredAccessorDescriptor> descriptor,
- void* setter_ignored,
- void* data_ignored,
- v8::AccessControl settings,
- v8::PropertyAttribute attributes,
- v8::Handle<AccessorSignature> signature) {
+ v8::Handle<String> name,
+ v8::Handle<v8::DeclaredAccessorDescriptor> descriptor,
+ void* setter_ignored,
+ void* data_ignored,
+ v8::AccessControl settings,
+ v8::PropertyAttribute attributes,
+ v8::Handle<AccessorSignature> signature) {
i::Isolate* isolate = Utils::OpenHandle(*name)->GetIsolate();
if (descriptor.IsEmpty()) return i::Handle<i::DeclaredAccessorInfo>();
i::Handle<i::DeclaredAccessorInfo> obj =
@@ -1274,8 +1237,11 @@
Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
- if (EmptyCheck("v8::FunctionTemplate::InstanceTemplate()", this))
+ if (!Utils::ApiCheck(this != NULL,
+ "v8::FunctionTemplate::InstanceTemplate()",
+ "Reading from empty handle")) {
return Local<ObjectTemplate>();
+ }
ENTER_V8(isolate);
i::Handle<i::FunctionTemplateInfo> handle = Utils::OpenHandle(this);
if (handle->instance_template()->IsUndefined()) {
@@ -1338,8 +1304,8 @@
Local<ObjectTemplate> ObjectTemplate::New(
- i::Isolate* isolate,
- v8::Handle<FunctionTemplate> constructor) {
+ i::Isolate* isolate,
+ v8::Handle<FunctionTemplate> constructor) {
EnsureInitializedForIsolate(isolate, "v8::ObjectTemplate::New()");
LOG_API(isolate, "ObjectTemplate::New");
ENTER_V8(isolate);
@@ -1508,10 +1474,10 @@
void ObjectTemplate::SetAccessCheckCallbacks(
- NamedSecurityCallback named_callback,
- IndexedSecurityCallback indexed_callback,
- Handle<Value> data,
- bool turned_on_by_default) {
+ NamedSecurityCallback named_callback,
+ IndexedSecurityCallback indexed_callback,
+ Handle<Value> data,
+ bool turned_on_by_default) {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
ENTER_V8(isolate);
i::HandleScope scope(isolate);
@@ -1539,12 +1505,12 @@
void ObjectTemplate::SetIndexedPropertyHandler(
- IndexedPropertyGetterCallback getter,
- IndexedPropertySetterCallback setter,
- IndexedPropertyQueryCallback query,
- IndexedPropertyDeleterCallback remover,
- IndexedPropertyEnumeratorCallback enumerator,
- Handle<Value> data) {
+ IndexedPropertyGetterCallback getter,
+ IndexedPropertySetterCallback setter,
+ IndexedPropertyQueryCallback query,
+ IndexedPropertyDeleterCallback remover,
+ IndexedPropertyEnumeratorCallback enumerator,
+ Handle<Value> data) {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
ENTER_V8(isolate);
i::HandleScope scope(isolate);
@@ -1600,9 +1566,9 @@
void ObjectTemplate::SetInternalFieldCount(int value) {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
- if (!ApiCheck(i::Smi::IsValid(value),
- "v8::ObjectTemplate::SetInternalFieldCount()",
- "Invalid internal field count")) {
+ if (!Utils::ApiCheck(i::Smi::IsValid(value),
+ "v8::ObjectTemplate::SetInternalFieldCount()",
+ "Invalid internal field count")) {
return;
}
ENTER_V8(isolate);
@@ -1619,22 +1585,12 @@
// --- S c r i p t D a t a ---
-ScriptData* ScriptData::PreCompile(v8::Isolate* isolate,
- const char* input,
- int length) {
- i::Utf8ToUtf16CharacterStream stream(
- reinterpret_cast<const unsigned char*>(input), length);
- return i::PreParserApi::PreParse(
- reinterpret_cast<i::Isolate*>(isolate), &stream);
-}
-
-
ScriptData* ScriptData::PreCompile(v8::Handle<String> source) {
i::Handle<i::String> str = Utils::OpenHandle(*source);
i::Isolate* isolate = str->GetIsolate();
if (str->IsExternalTwoByteString()) {
i::ExternalTwoByteStringUtf16CharacterStream stream(
- i::Handle<i::ExternalTwoByteString>::cast(str), 0, str->length());
+ i::Handle<i::ExternalTwoByteString>::cast(str), 0, str->length());
return i::PreParserApi::PreParse(isolate, &stream);
} else {
i::GenericStringUtf16CharacterStream stream(str, 0, str->length());
@@ -1711,16 +1667,16 @@
pre_data_impl = NULL;
}
i::Handle<i::SharedFunctionInfo> result =
- i::Compiler::CompileScript(str,
- name_obj,
- line_offset,
- column_offset,
- is_shared_cross_origin,
- isolate->global_context(),
- NULL,
- pre_data_impl,
- Utils::OpenHandle(*script_data, true),
- i::NOT_NATIVES_CODE);
+ i::Compiler::CompileScript(str,
+ name_obj,
+ line_offset,
+ column_offset,
+ is_shared_cross_origin,
+ isolate->global_context(),
+ NULL,
+ pre_data_impl,
+ Utils::OpenHandle(*script_data, true),
+ i::NOT_NATIVES_CODE);
has_pending_exception = result.is_null();
EXCEPTION_BAILOUT_CHECK(isolate, Local<Script>());
raw_result = *result;
@@ -2425,23 +2381,23 @@
}
-#define TYPED_ARRAY_LIST(F) \
-F(Uint8Array, kExternalUnsignedByteArray) \
-F(Int8Array, kExternalByteArray) \
-F(Uint16Array, kExternalUnsignedShortArray) \
-F(Int16Array, kExternalShortArray) \
-F(Uint32Array, kExternalUnsignedIntArray) \
-F(Int32Array, kExternalIntArray) \
-F(Float32Array, kExternalFloatArray) \
-F(Float64Array, kExternalDoubleArray) \
-F(Uint8ClampedArray, kExternalPixelArray)
+#define TYPED_ARRAY_LIST(F) \
+ F(Uint8Array, kExternalUnsignedByteArray) \
+ F(Int8Array, kExternalByteArray) \
+ F(Uint16Array, kExternalUnsignedShortArray) \
+ F(Int16Array, kExternalShortArray) \
+ F(Uint32Array, kExternalUnsignedIntArray) \
+ F(Int32Array, kExternalIntArray) \
+ F(Float32Array, kExternalFloatArray) \
+ F(Float64Array, kExternalDoubleArray) \
+ F(Uint8ClampedArray, kExternalPixelArray)
-#define VALUE_IS_TYPED_ARRAY(TypedArray, type_const) \
- bool Value::Is##TypedArray() const { \
- i::Handle<i::Object> obj = Utils::OpenHandle(this); \
- if (!obj->IsJSTypedArray()) return false; \
- return i::JSTypedArray::cast(*obj)->type() == type_const; \
+#define VALUE_IS_TYPED_ARRAY(TypedArray, type_const) \
+ bool Value::Is##TypedArray() const { \
+ i::Handle<i::Object> obj = Utils::OpenHandle(this); \
+ if (!obj->IsJSTypedArray()) return false; \
+ return i::JSTypedArray::cast(*obj)->type() == type_const; \
}
TYPED_ARRAY_LIST(VALUE_IS_TYPED_ARRAY)
@@ -2490,9 +2446,9 @@
if (obj->IsNumber()) {
double value = obj->Number();
return !i::IsMinusZero(value) &&
- value >= 0 &&
- value <= i::kMaxUInt32 &&
- value == i::FastUI2D(i::FastD2UI(value));
+ value >= 0 &&
+ value <= i::kMaxUInt32 &&
+ value == i::FastUI2D(i::FastD2UI(value));
}
return false;
}
@@ -2544,7 +2500,7 @@
if (!constr->IsJSFunction()) return false;
i::JSFunction* func = i::JSFunction::cast(constr);
return func->shared()->native() &&
- constr == LookupBuiltin(isolate, class_name);
+ constr == LookupBuiltin(isolate, class_name);
}
@@ -2681,106 +2637,108 @@
void i::Internals::CheckInitializedImpl(v8::Isolate* external_isolate) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
- ApiCheck(isolate != NULL && isolate->IsInitialized() && !isolate->IsDead(),
- "v8::internal::Internals::CheckInitialized()",
- "Isolate is not initialized or V8 has died");
+ Utils::ApiCheck(isolate != NULL &&
+ isolate->IsInitialized() &&
+ !isolate->IsDead(),
+ "v8::internal::Internals::CheckInitialized()",
+ "Isolate is not initialized or V8 has died");
}
void External::CheckCast(v8::Value* that) {
- ApiCheck(Utils::OpenHandle(that)->IsExternal(),
- "v8::External::Cast()",
- "Could not convert to external");
+ Utils::ApiCheck(Utils::OpenHandle(that)->IsExternal(),
+ "v8::External::Cast()",
+ "Could not convert to external");
}
void v8::Object::CheckCast(Value* that) {
i::Handle<i::Object> obj = Utils::OpenHandle(that);
- ApiCheck(obj->IsJSObject(),
- "v8::Object::Cast()",
- "Could not convert to object");
+ Utils::ApiCheck(obj->IsJSObject(),
+ "v8::Object::Cast()",
+ "Could not convert to object");
}
void v8::Function::CheckCast(Value* that) {
i::Handle<i::Object> obj = Utils::OpenHandle(that);
- ApiCheck(obj->IsJSFunction(),
- "v8::Function::Cast()",
- "Could not convert to function");
+ Utils::ApiCheck(obj->IsJSFunction(),
+ "v8::Function::Cast()",
+ "Could not convert to function");
}
void v8::String::CheckCast(v8::Value* that) {
i::Handle<i::Object> obj = Utils::OpenHandle(that);
- ApiCheck(obj->IsString(),
- "v8::String::Cast()",
- "Could not convert to string");
+ Utils::ApiCheck(obj->IsString(),
+ "v8::String::Cast()",
+ "Could not convert to string");
}
void v8::Symbol::CheckCast(v8::Value* that) {
i::Handle<i::Object> obj = Utils::OpenHandle(that);
- ApiCheck(obj->IsSymbol(),
- "v8::Symbol::Cast()",
- "Could not convert to symbol");
+ Utils::ApiCheck(obj->IsSymbol(),
+ "v8::Symbol::Cast()",
+ "Could not convert to symbol");
}
void v8::Number::CheckCast(v8::Value* that) {
i::Handle<i::Object> obj = Utils::OpenHandle(that);
- ApiCheck(obj->IsNumber(),
- "v8::Number::Cast()",
- "Could not convert to number");
+ Utils::ApiCheck(obj->IsNumber(),
+ "v8::Number::Cast()",
+ "Could not convert to number");
}
void v8::Integer::CheckCast(v8::Value* that) {
i::Handle<i::Object> obj = Utils::OpenHandle(that);
- ApiCheck(obj->IsNumber(),
- "v8::Integer::Cast()",
- "Could not convert to number");
+ Utils::ApiCheck(obj->IsNumber(),
+ "v8::Integer::Cast()",
+ "Could not convert to number");
}
void v8::Array::CheckCast(Value* that) {
i::Handle<i::Object> obj = Utils::OpenHandle(that);
- ApiCheck(obj->IsJSArray(),
- "v8::Array::Cast()",
- "Could not convert to array");
+ Utils::ApiCheck(obj->IsJSArray(),
+ "v8::Array::Cast()",
+ "Could not convert to array");
}
void v8::ArrayBuffer::CheckCast(Value* that) {
i::Handle<i::Object> obj = Utils::OpenHandle(that);
- ApiCheck(obj->IsJSArrayBuffer(),
- "v8::ArrayBuffer::Cast()",
- "Could not convert to ArrayBuffer");
+ Utils::ApiCheck(obj->IsJSArrayBuffer(),
+ "v8::ArrayBuffer::Cast()",
+ "Could not convert to ArrayBuffer");
}
void v8::ArrayBufferView::CheckCast(Value* that) {
i::Handle<i::Object> obj = Utils::OpenHandle(that);
- ApiCheck(obj->IsJSArrayBufferView(),
- "v8::ArrayBufferView::Cast()",
- "Could not convert to ArrayBufferView");
+ Utils::ApiCheck(obj->IsJSArrayBufferView(),
+ "v8::ArrayBufferView::Cast()",
+ "Could not convert to ArrayBufferView");
}
void v8::TypedArray::CheckCast(Value* that) {
i::Handle<i::Object> obj = Utils::OpenHandle(that);
- ApiCheck(obj->IsJSTypedArray(),
- "v8::TypedArray::Cast()",
- "Could not convert to TypedArray");
+ Utils::ApiCheck(obj->IsJSTypedArray(),
+ "v8::TypedArray::Cast()",
+ "Could not convert to TypedArray");
}
-#define CHECK_TYPED_ARRAY_CAST(ApiClass, typeConst) \
- void v8::ApiClass::CheckCast(Value* that) { \
- i::Handle<i::Object> obj = Utils::OpenHandle(that); \
- ApiCheck(obj->IsJSTypedArray() && \
- i::JSTypedArray::cast(*obj)->type() == typeConst, \
- "v8::" #ApiClass "::Cast()", \
- "Could not convert to " #ApiClass); \
+#define CHECK_TYPED_ARRAY_CAST(ApiClass, typeConst) \
+ void v8::ApiClass::CheckCast(Value* that) { \
+ i::Handle<i::Object> obj = Utils::OpenHandle(that); \
+ Utils::ApiCheck(obj->IsJSTypedArray() && \
+ i::JSTypedArray::cast(*obj)->type() == typeConst, \
+ "v8::" #ApiClass "::Cast()", \
+ "Could not convert to " #ApiClass); \
}
@@ -2791,62 +2749,62 @@
void v8::DataView::CheckCast(Value* that) {
i::Handle<i::Object> obj = Utils::OpenHandle(that);
- ApiCheck(obj->IsJSDataView(),
- "v8::DataView::Cast()",
- "Could not convert to DataView");
+ Utils::ApiCheck(obj->IsJSDataView(),
+ "v8::DataView::Cast()",
+ "Could not convert to DataView");
}
void v8::Date::CheckCast(v8::Value* that) {
i::Isolate* isolate = i::Isolate::Current();
i::Handle<i::Object> obj = Utils::OpenHandle(that);
- ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Date_string()),
- "v8::Date::Cast()",
- "Could not convert to date");
+ Utils::ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Date_string()),
+ "v8::Date::Cast()",
+ "Could not convert to date");
}
void v8::StringObject::CheckCast(v8::Value* that) {
i::Isolate* isolate = i::Isolate::Current();
i::Handle<i::Object> obj = Utils::OpenHandle(that);
- ApiCheck(obj->HasSpecificClassOf(isolate->heap()->String_string()),
- "v8::StringObject::Cast()",
- "Could not convert to StringObject");
+ Utils::ApiCheck(obj->HasSpecificClassOf(isolate->heap()->String_string()),
+ "v8::StringObject::Cast()",
+ "Could not convert to StringObject");
}
void v8::SymbolObject::CheckCast(v8::Value* that) {
i::Isolate* isolate = i::Isolate::Current();
i::Handle<i::Object> obj = Utils::OpenHandle(that);
- ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Symbol_string()),
- "v8::SymbolObject::Cast()",
- "Could not convert to SymbolObject");
+ Utils::ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Symbol_string()),
+ "v8::SymbolObject::Cast()",
+ "Could not convert to SymbolObject");
}
void v8::NumberObject::CheckCast(v8::Value* that) {
i::Isolate* isolate = i::Isolate::Current();
i::Handle<i::Object> obj = Utils::OpenHandle(that);
- ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Number_string()),
- "v8::NumberObject::Cast()",
- "Could not convert to NumberObject");
+ Utils::ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Number_string()),
+ "v8::NumberObject::Cast()",
+ "Could not convert to NumberObject");
}
void v8::BooleanObject::CheckCast(v8::Value* that) {
i::Isolate* isolate = i::Isolate::Current();
i::Handle<i::Object> obj = Utils::OpenHandle(that);
- ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Boolean_string()),
- "v8::BooleanObject::Cast()",
- "Could not convert to BooleanObject");
+ Utils::ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Boolean_string()),
+ "v8::BooleanObject::Cast()",
+ "Could not convert to BooleanObject");
}
void v8::RegExp::CheckCast(v8::Value* that) {
i::Handle<i::Object> obj = Utils::OpenHandle(that);
- ApiCheck(obj->IsJSRegExp(),
- "v8::RegExp::Cast()",
- "Could not convert to regular expression");
+ Utils::ApiCheck(obj->IsJSRegExp(),
+ "v8::RegExp::Cast()",
+ "Could not convert to regular expression");
}
@@ -2978,8 +2936,9 @@
bool Value::Equals(Handle<Value> that) const {
i::Isolate* isolate = i::Isolate::Current();
- if (EmptyCheck("v8::Value::Equals()", this) ||
- EmptyCheck("v8::Value::Equals()", that)) {
+ if (!Utils::ApiCheck(this != NULL && !that.IsEmpty(),
+ "v8::Value::Equals()",
+ "Reading from empty handle")) {
return false;
}
LOG_API(isolate, "Equals");
@@ -3004,8 +2963,9 @@
bool Value::StrictEquals(Handle<Value> that) const {
i::Isolate* isolate = i::Isolate::Current();
- if (EmptyCheck("v8::Value::StrictEquals()", this) ||
- EmptyCheck("v8::Value::StrictEquals()", that)) {
+ if (!Utils::ApiCheck(this != NULL && !that.IsEmpty(),
+ "v8::Value::StrictEquals()",
+ "Reading from empty handle")) {
return false;
}
LOG_API(isolate, "StrictEquals");
@@ -3024,7 +2984,7 @@
return other->IsNumber() && obj->Number() == other->Number();
} else if (obj->IsString()) {
return other->IsString() &&
- i::String::cast(*obj)->Equals(i::String::cast(*other));
+ i::String::cast(*obj)->Equals(i::String::cast(*other));
} else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
return other->IsUndefined() || other->IsUndetectableObject();
} else {
@@ -3035,8 +2995,9 @@
bool Value::SameValue(Handle<Value> that) const {
i::Isolate* isolate = i::Isolate::Current();
- if (EmptyCheck("v8::Value::SameValue()", this) ||
- EmptyCheck("v8::Value::SameValue()", that)) {
+ if (!Utils::ApiCheck(this != NULL && !that.IsEmpty(),
+ "v8::Value::SameValue()",
+ "Reading from empty handle")) {
return false;
}
LOG_API(isolate, "SameValue");
@@ -3559,7 +3520,7 @@
Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
- Handle<String> key) {
+ Handle<String> key) {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
ON_BAILOUT(isolate,
"v8::Object::GetRealNamedPropertyInPrototypeChain()",
@@ -3772,15 +3733,16 @@
ON_BAILOUT(isolate, "v8::SetElementsToPixelData()", return);
ENTER_V8(isolate);
i::HandleScope scope(isolate);
- if (!ApiCheck(length >= 0 && length <= i::ExternalPixelArray::kMaxLength,
- "v8::Object::SetIndexedPropertiesToPixelData()",
- "length exceeds max acceptable value")) {
+ if (!Utils::ApiCheck(length >= 0 &&
+ length <= i::ExternalPixelArray::kMaxLength,
+ "v8::Object::SetIndexedPropertiesToPixelData()",
+ "length exceeds max acceptable value")) {
return;
}
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
- if (!ApiCheck(!self->IsJSArray(),
- "v8::Object::SetIndexedPropertiesToPixelData()",
- "JSArray is not supported")) {
+ if (!Utils::ApiCheck(!self->IsJSArray(),
+ "v8::Object::SetIndexedPropertiesToPixelData()",
+ "JSArray is not supported")) {
return;
}
PrepareExternalArrayElements(self, data, kExternalPixelArray, length);
@@ -3828,15 +3790,15 @@
ON_BAILOUT(isolate, "v8::SetIndexedPropertiesToExternalArrayData()", return);
ENTER_V8(isolate);
i::HandleScope scope(isolate);
- if (!ApiCheck(length >= 0 && length <= i::ExternalArray::kMaxLength,
- "v8::Object::SetIndexedPropertiesToExternalArrayData()",
- "length exceeds max acceptable value")) {
+ if (!Utils::ApiCheck(length >= 0 && length <= i::ExternalArray::kMaxLength,
+ "v8::Object::SetIndexedPropertiesToExternalArrayData()",
+ "length exceeds max acceptable value")) {
return;
}
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
- if (!ApiCheck(!self->IsJSArray(),
- "v8::Object::SetIndexedPropertiesToExternalArrayData()",
- "JSArray is not supported")) {
+ if (!Utils::ApiCheck(!self->IsJSArray(),
+ "v8::Object::SetIndexedPropertiesToExternalArrayData()",
+ "JSArray is not supported")) {
return;
}
PrepareExternalArrayElements(self, data, array_type, length);
@@ -4000,7 +3962,7 @@
ENTER_V8(isolate);
return FunctionTemplateNew(
isolate, callback, data, Local<Signature>(), length, true)->
- GetFunction();
+ GetFunction();
}
@@ -4083,7 +4045,7 @@
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
ON_BAILOUT(isolate, "v8::Function::GetDisplayName()",
return ToApiHandle<Primitive>(
- isolate->factory()->undefined_value()));
+ isolate->factory()->undefined_value()));
ENTER_V8(isolate);
i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
i::Handle<i::String> property_name =
@@ -4109,9 +4071,9 @@
i::Handle<i::Object> scriptName = GetScriptNameOrSourceURL(script);
v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(func->GetIsolate());
v8::ScriptOrigin origin(
- Utils::ToLocal(scriptName),
- v8::Integer::New(isolate, script->line_offset()->value()),
- v8::Integer::New(isolate, script->column_offset()->value()));
+ Utils::ToLocal(scriptName),
+ v8::Integer::New(isolate, script->line_offset()->value()),
+ v8::Integer::New(isolate, script->column_offset()->value()));
return origin;
}
return v8::ScriptOrigin(Handle<Value>());
@@ -4198,7 +4160,7 @@
static inline const uint16_t* Align(const uint16_t* chars) {
return reinterpret_cast<uint16_t*>(
- reinterpret_cast<uintptr_t>(chars) & ~kAlignmentMask);
+ reinterpret_cast<uintptr_t>(chars) & ~kAlignmentMask);
}
class ContainsOnlyOneByteHelper {
@@ -4218,7 +4180,7 @@
// Align to uintptr_t.
const uint16_t* end = chars + length;
while (Unaligned(chars) && chars != end) {
- acc |= *chars++;
+ acc |= *chars++;
}
// Read word aligned in blocks,
// checking the return value at the end of each block.
@@ -4322,8 +4284,8 @@
class Visitor {
public:
inline explicit Visitor()
- : utf8_length_(0),
- state_(kInitialState) {}
+ : utf8_length_(0),
+ state_(kInitialState) {}
void VisitOneByteString(const uint8_t* chars, int length) {
int utf8_length = 0;
@@ -4396,7 +4358,7 @@
if (!(*state & kRightmostEdgeIsCalculated)) {
ASSERT(!(*state & kRightmostEdgeIsSurrogate));
*state |= (kRightmostEdgeIsCalculated
- | (edge_surrogate ? kRightmostEdgeIsSurrogate : 0));
+ | (edge_surrogate ? kRightmostEdgeIsSurrogate : 0));
} else if (edge_surrogate && StartsWithSurrogate(*state)) {
*length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates;
}
@@ -4503,13 +4465,13 @@
public:
Utf8WriterVisitor(
char* buffer, int capacity, bool skip_capacity_check)
- : early_termination_(false),
- last_character_(unibrow::Utf16::kNoPreviousCharacter),
- buffer_(buffer),
- start_(buffer),
- capacity_(capacity),
- skip_capacity_check_(capacity == -1 || skip_capacity_check),
- utf16_chars_read_(0) {
+ : early_termination_(false),
+ last_character_(unibrow::Utf16::kNoPreviousCharacter),
+ buffer_(buffer),
+ start_(buffer),
+ capacity_(capacity),
+ skip_capacity_check_(capacity == -1 || skip_capacity_check),
+ utf16_chars_read_(0) {
}
static int WriteEndCharacter(uint16_t character,
@@ -4656,8 +4618,8 @@
static bool RecursivelySerializeToUtf8(i::String* current,
- Utf8WriterVisitor* writer,
- int recursion_budget) {
+ Utf8WriterVisitor* writer,
+ int recursion_budget) {
while (!writer->IsDone()) {
i::ConsString* cons_string = i::String::VisitFlat(writer, current);
if (cons_string == NULL) return true; // Leaf node.
@@ -4815,14 +4777,14 @@
} else {
expected = NULL;
expectedEncoding = str->IsOneByteRepresentation() ? ASCII_ENCODING
- : TWO_BYTE_ENCODING;
+ : TWO_BYTE_ENCODING;
}
CHECK_EQ(expected, value);
CHECK_EQ(expectedEncoding, encoding);
}
const v8::String::ExternalAsciiStringResource*
- v8::String::GetExternalAsciiStringResource() const {
+v8::String::GetExternalAsciiStringResource() const {
i::Handle<i::String> str = Utils::OpenHandle(this);
if (i::StringShape(*str).IsExternalAscii()) {
const void* resource =
@@ -4897,9 +4859,9 @@
static bool InternalFieldOK(i::Handle<i::JSObject> obj,
int index,
const char* location) {
- return ApiCheck(index < obj->GetInternalFieldCount(),
- location,
- "Internal field out of bounds");
+ return Utils::ApiCheck(index < obj->GetInternalFieldCount(),
+ location,
+ "Internal field out of bounds");
}
@@ -4983,7 +4945,7 @@
void v8::V8::SetReturnAddressLocationResolver(
- ReturnAddressLocationResolver return_address_resolver) {
+ ReturnAddressLocationResolver return_address_resolver) {
i::V8::SetReturnAddressLocationResolver(return_address_resolver);
}
@@ -5021,9 +4983,9 @@
void v8::V8::SetArrayBufferAllocator(
ArrayBuffer::Allocator* allocator) {
- if (!ApiCheck(i::V8::ArrayBufferAllocator() == NULL,
- "v8::V8::SetArrayBufferAllocator",
- "ArrayBufferAllocator might only be set once"))
+ if (!Utils::ApiCheck(i::V8::ArrayBufferAllocator() == NULL,
+ "v8::V8::SetArrayBufferAllocator",
+ "ArrayBufferAllocator might only be set once"))
return;
i::V8::SetArrayBufferAllocator(allocator);
}
@@ -5031,9 +4993,9 @@
bool v8::V8::Dispose() {
i::Isolate* isolate = i::Isolate::Current();
- if (!ApiCheck(isolate != NULL && isolate->IsDefaultIsolate(),
- "v8::V8::Dispose()",
- "Use v8::Isolate::Dispose() for a non-default isolate.")) {
+ if (!Utils::ApiCheck(isolate != NULL && isolate->IsDefaultIsolate(),
+ "v8::V8::Dispose()",
+ "Use v8::Isolate::Dispose() for non-default isolate.")) {
return false;
}
i::V8::TearDown();
@@ -5252,7 +5214,7 @@
// but can't presently as calls to GetProtoype will return the wrong result.
if (i::Handle<i::JSGlobalProxy>::cast(
global)->IsDetachedFrom(context->global_object())) {
- global = i::Handle<i::Object>(context->global_object(), isolate);
+ global = i::Handle<i::Object>(context->global_object(), isolate);
}
return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
}
@@ -5472,25 +5434,23 @@
}
-i::Handle<i::String> NewExternalStringHandle(i::Isolate* isolate,
- v8::String::ExternalStringResource* resource) {
- i::Handle<i::String> result =
- isolate->factory()->NewExternalStringFromTwoByte(resource);
- return result;
+static i::Handle<i::String> NewExternalStringHandle(
+ i::Isolate* isolate,
+ v8::String::ExternalStringResource* resource) {
+ return isolate->factory()->NewExternalStringFromTwoByte(resource);
}
-i::Handle<i::String> NewExternalAsciiStringHandle(i::Isolate* isolate,
- v8::String::ExternalAsciiStringResource* resource) {
- i::Handle<i::String> result =
- isolate->factory()->NewExternalStringFromAscii(resource);
- return result;
+static i::Handle<i::String> NewExternalAsciiStringHandle(
+ i::Isolate* isolate,
+ v8::String::ExternalAsciiStringResource* resource) {
+ return isolate->factory()->NewExternalStringFromAscii(resource);
}
-bool RedirectToExternalString(i::Isolate* isolate,
- i::Handle<i::String> parent,
- i::Handle<i::String> external) {
+static bool RedirectToExternalString(i::Isolate* isolate,
+ i::Handle<i::String> parent,
+ i::Handle<i::String> external) {
if (parent->IsConsString()) {
i::Handle<i::ConsString> cons = i::Handle<i::ConsString>::cast(parent);
cons->set_first(*external);
@@ -5506,8 +5466,8 @@
Local<String> v8::String::NewExternal(
- Isolate* isolate,
- v8::String::ExternalStringResource* resource) {
+ Isolate* isolate,
+ v8::String::ExternalStringResource* resource) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
EnsureInitializedForIsolate(i_isolate, "v8::String::NewExternal()");
LOG_API(i_isolate, "String::NewExternal");
@@ -5556,8 +5516,8 @@
Local<String> v8::String::NewExternal(
- Isolate* isolate,
- v8::String::ExternalAsciiStringResource* resource) {
+ Isolate* isolate,
+ v8::String::ExternalAsciiStringResource* resource) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
EnsureInitializedForIsolate(i_isolate, "v8::String::NewExternal()");
LOG_API(i_isolate, "String::NewExternal");
@@ -5819,8 +5779,8 @@
// Assert that the static flags cast in GetFlags is valid.
-#define REGEXP_FLAG_ASSERT_EQ(api_flag, internal_flag) \
- STATIC_ASSERT(static_cast<int>(v8::RegExp::api_flag) == \
+#define REGEXP_FLAG_ASSERT_EQ(api_flag, internal_flag) \
+ STATIC_ASSERT(static_cast<int>(v8::RegExp::api_flag) == \
static_cast<int>(i::JSRegExp::internal_flag))
REGEXP_FLAG_ASSERT_EQ(kNone, NONE);
REGEXP_FLAG_ASSERT_EQ(kGlobal, GLOBAL);
@@ -5888,9 +5848,9 @@
v8::ArrayBuffer::Contents v8::ArrayBuffer::Externalize() {
i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
- ApiCheck(!obj->is_external(),
- "v8::ArrayBuffer::Externalize",
- "ArrayBuffer already externalized");
+ Utils::ApiCheck(!obj->is_external(),
+ "v8::ArrayBuffer::Externalize",
+ "ArrayBuffer already externalized");
obj->set_is_external(true);
size_t byte_length = static_cast<size_t>(obj->byte_length()->Number());
Contents contents;
@@ -5903,9 +5863,9 @@
void v8::ArrayBuffer::Neuter() {
i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
i::Isolate* isolate = obj->GetIsolate();
- ApiCheck(obj->is_external(),
- "v8::ArrayBuffer::Neuter",
- "Only externalized ArrayBuffers can be neutered");
+ Utils::ApiCheck(obj->is_external(),
+ "v8::ArrayBuffer::Neuter",
+ "Only externalized ArrayBuffers can be neutered");
LOG_API(obj->GetIsolate(), "v8::ArrayBuffer::Neuter()");
ENTER_V8(isolate);
@@ -5989,7 +5949,7 @@
size_t byte_offset,
size_t byte_length) {
ASSERT(byte_offset + byte_length <=
- static_cast<size_t>(buffer->byte_length()->Number()));
+ static_cast<size_t>(buffer->byte_length()->Number()));
obj->set_buffer(*buffer);
@@ -5997,11 +5957,11 @@
buffer->set_weak_first_view(*obj);
i::Handle<i::Object> byte_offset_object =
- isolate->factory()->NewNumberFromSize(byte_offset);
+ isolate->factory()->NewNumberFromSize(byte_offset);
obj->set_byte_offset(*byte_offset_object);
i::Handle<i::Object> byte_length_object =
- isolate->factory()->NewNumberFromSize(byte_length);
+ isolate->factory()->NewNumberFromSize(byte_length);
obj->set_byte_length(*byte_length_object);
}
@@ -6023,7 +5983,7 @@
isolate, obj, buffer, byte_offset, byte_length);
i::Handle<i::Object> length_object =
- isolate->factory()->NewNumberFromSize(length);
+ isolate->factory()->NewNumberFromSize(length);
obj->set_length(*length_object);
i::Handle<i::ExternalArray> elements =
@@ -6175,7 +6135,7 @@
NeanderObject obj(isolate, 2);
obj.set(0, *isolate->factory()->NewForeign(FUNCTION_ADDR(that)));
obj.set(1, data.IsEmpty() ? isolate->heap()->undefined_value()
- : *Utils::OpenHandle(*data));
+ : *Utils::OpenHandle(*data));
listeners.add(obj.value());
return true;
}
@@ -6201,9 +6161,9 @@
void V8::SetCaptureStackTraceForUncaughtExceptions(
- bool capture,
- int frame_limit,
- StackTrace::StackTraceOptions options) {
+ bool capture,
+ int frame_limit,
+ StackTrace::StackTraceOptions options) {
i::Isolate::Current()->SetCaptureStackTraceForUncaughtExceptions(
capture,
frame_limit,
@@ -6232,7 +6192,7 @@
}
void V8::SetFailedAccessCheckCallbackFunction(
- FailedAccessCheckCallback callback) {
+ FailedAccessCheckCallback callback) {
i::Isolate* isolate = i::Isolate::Current();
isolate->SetFailedAccessCheckCallback(callback);
}
@@ -6452,6 +6412,21 @@
}
+void Isolate::RequestGarbageCollectionForTesting(GarbageCollectionType type) {
+ CHECK(i::FLAG_expose_gc);
+ if (type == kMinorGarbageCollection) {
+ reinterpret_cast<i::Isolate*>(this)->heap()->CollectGarbage(
+ i::NEW_SPACE, "Isolate::RequestGarbageCollection",
+ kGCCallbackFlagForced);
+ } else {
+ ASSERT_EQ(kFullGarbageCollection, type);
+ reinterpret_cast<i::Isolate*>(this)->heap()->CollectAllGarbage(
+ i::Heap::kNoGCFlags, "Isolate::RequestGarbageCollection",
+ kGCCallbackFlagForced);
+ }
+}
+
+
Isolate* Isolate::GetCurrent() {
i::Isolate* isolate = i::Isolate::UncheckedCurrent();
return reinterpret_cast<Isolate*>(isolate);
@@ -6466,9 +6441,9 @@
void Isolate::Dispose() {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
- if (!ApiCheck(!isolate->IsInUse(),
- "v8::Isolate::Dispose()",
- "Disposing the isolate that is entered by a thread.")) {
+ if (!Utils::ApiCheck(!isolate->IsInUse(),
+ "v8::Isolate::Dispose()",
+ "Disposing the isolate that is entered by a thread.")) {
return;
}
isolate->TearDown();
@@ -7130,15 +7105,15 @@
void HeapSnapshot::Serialize(OutputStream* stream,
HeapSnapshot::SerializationFormat format) const {
- ApiCheck(format == kJSON,
- "v8::HeapSnapshot::Serialize",
- "Unknown serialization format");
- ApiCheck(stream->GetOutputEncoding() == OutputStream::kAscii,
- "v8::HeapSnapshot::Serialize",
- "Unsupported output encoding");
- ApiCheck(stream->GetChunkSize() > 0,
- "v8::HeapSnapshot::Serialize",
- "Invalid stream chunk size");
+ Utils::ApiCheck(format == kJSON,
+ "v8::HeapSnapshot::Serialize",
+ "Unknown serialization format");
+ Utils::ApiCheck(stream->GetOutputEncoding() == OutputStream::kAscii,
+ "v8::HeapSnapshot::Serialize",
+ "Unsupported output encoding");
+ Utils::ApiCheck(stream->GetChunkSize() > 0,
+ "v8::HeapSnapshot::Serialize",
+ "Invalid stream chunk size");
i::HeapSnapshotJSONSerializer serializer(ToInternal(this));
serializer.Serialize(stream);
}
diff --git a/src/api.h b/src/api.h
index aa3c38c..6091aa1 100644
--- a/src/api.h
+++ b/src/api.h
@@ -196,7 +196,12 @@
class Utils {
public:
- static bool ReportApiFailure(const char* location, const char* message);
+ static inline bool ApiCheck(bool condition,
+ const char* location,
+ const char* message) {
+ if (!condition) Utils::ReportApiFailure(location, message);
+ return condition;
+ }
static Local<FunctionTemplate> ToFunctionTemplate(NeanderObject obj);
static Local<ObjectTemplate> ToObjectTemplate(NeanderObject obj);
@@ -303,6 +308,9 @@
static inline v8::internal::Handle<To> OpenHandle(v8::Local<From> handle) {
return OpenHandle(*handle);
}
+
+ private:
+ static void ReportApiFailure(const char* location, const char* message);
};
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index 4e7b248..d9449d5 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -1351,13 +1351,13 @@
{
AllowExternalCallThatCantCauseGC scope(masm);
__ PrepareCallCFunction(0, 2, scratch);
- __ SetCallCDoubleArguments(double_base, double_exponent);
+ __ MovToFloatParameters(double_base, double_exponent);
__ CallCFunction(
ExternalReference::power_double_double_function(masm->isolate()),
0, 2);
}
__ pop(lr);
- __ GetCFunctionDoubleResult(double_result);
+ __ MovFromFloatResult(double_result);
__ jmp(&done);
__ bind(&int_exponent_convert);
@@ -1425,13 +1425,13 @@
{
AllowExternalCallThatCantCauseGC scope(masm);
__ PrepareCallCFunction(0, 2, scratch);
- __ SetCallCDoubleArguments(double_base, double_exponent);
+ __ MovToFloatParameters(double_base, double_exponent);
__ CallCFunction(
ExternalReference::power_double_double_function(masm->isolate()),
0, 2);
}
__ pop(lr);
- __ GetCFunctionDoubleResult(double_result);
+ __ MovFromFloatResult(double_result);
__ bind(&done);
__ IncrementCounter(counters->math_pow(), 1, scratch, scratch2);
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index 5477b24..c850742 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -357,9 +357,9 @@
MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size));
- __ GetCFunctionDoubleResult(d0);
+ __ MovFromFloatParameter(d0);
__ vsqrt(d0, d0);
- __ SetCallCDoubleArguments(d0);
+ __ MovToFloatResult(d0);
__ Ret();
CodeDesc desc;
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 8888ec6..d2c9a25 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -2128,12 +2128,12 @@
break;
case Token::MOD: {
__ PrepareCallCFunction(0, 2, scratch0());
- __ SetCallCDoubleArguments(left, right);
+ __ MovToFloatParameters(left, right);
__ CallCFunction(
ExternalReference::mod_two_doubles_operation(isolate()),
0, 2);
// Move the result in the double result register.
- __ GetCFunctionDoubleResult(result);
+ __ MovFromFloatResult(result);
break;
}
default:
@@ -3934,10 +3934,10 @@
void LCodeGen::DoMathLog(LMathLog* instr) {
__ PrepareCallCFunction(0, 1, scratch0());
- __ SetCallCDoubleArguments(ToDoubleRegister(instr->value()));
+ __ MovToFloatParameter(ToDoubleRegister(instr->value()));
__ CallCFunction(ExternalReference::math_log_double_function(isolate()),
0, 1);
- __ GetCFunctionDoubleResult(ToDoubleRegister(instr->result()));
+ __ MovFromFloatResult(ToDoubleRegister(instr->result()));
}
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index 97d05a6..38ab0e9 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -1081,7 +1081,7 @@
}
-void MacroAssembler::GetCFunctionDoubleResult(const DwVfpRegister dst) {
+void MacroAssembler::MovFromFloatResult(const DwVfpRegister dst) {
if (use_eabi_hardfloat()) {
Move(dst, d0);
} else {
@@ -1090,6 +1090,12 @@
}
+// On ARM this is just a synonym to make the purpose clear.
+void MacroAssembler::MovFromFloatParameter(DwVfpRegister dst) {
+ MovFromFloatResult(dst);
+}
+
+
void MacroAssembler::SetCallKind(Register dst, CallKind call_kind) {
// This macro takes the dst register to make the code more readable
// at the call sites. However, the dst register has to be r5 to
@@ -3540,33 +3546,27 @@
}
-void MacroAssembler::SetCallCDoubleArguments(DwVfpRegister dreg) {
- ASSERT(dreg.is(d0));
+void MacroAssembler::MovToFloatParameter(DwVfpRegister src) {
+ ASSERT(src.is(d0));
if (!use_eabi_hardfloat()) {
- vmov(r0, r1, dreg);
+ vmov(r0, r1, src);
}
}
-void MacroAssembler::SetCallCDoubleArguments(DwVfpRegister dreg1,
- DwVfpRegister dreg2) {
- ASSERT(dreg1.is(d0));
- ASSERT(dreg2.is(d1));
- if (!use_eabi_hardfloat()) {
- vmov(r0, r1, dreg1);
- vmov(r2, r3, dreg2);
- }
+// On ARM this is just a synonym to make the purpose clear.
+void MacroAssembler::MovToFloatResult(DwVfpRegister src) {
+ MovToFloatParameter(src);
}
-void MacroAssembler::SetCallCDoubleArguments(DwVfpRegister dreg,
- Register reg) {
- ASSERT(dreg.is(d0));
- if (use_eabi_hardfloat()) {
- Move(r0, reg);
- } else {
- Move(r2, reg);
- vmov(r0, r1, dreg);
+void MacroAssembler::MovToFloatParameters(DwVfpRegister src1,
+ DwVfpRegister src2) {
+ ASSERT(src1.is(d0));
+ ASSERT(src2.is(d1));
+ if (!use_eabi_hardfloat()) {
+ vmov(r0, r1, src1);
+ vmov(r2, r3, src2);
}
}
diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
index c4feb3e..3a133b9 100644
--- a/src/arm/macro-assembler-arm.h
+++ b/src/arm/macro-assembler-arm.h
@@ -1125,9 +1125,9 @@
// whether soft or hard floating point ABI is used. These functions
// abstract parameter passing for the three different ways we call
// C functions from generated code.
- void SetCallCDoubleArguments(DwVfpRegister dreg);
- void SetCallCDoubleArguments(DwVfpRegister dreg1, DwVfpRegister dreg2);
- void SetCallCDoubleArguments(DwVfpRegister dreg, Register reg);
+ void MovToFloatParameter(DwVfpRegister src);
+ void MovToFloatParameters(DwVfpRegister src1, DwVfpRegister src2);
+ void MovToFloatResult(DwVfpRegister src);
// Calls a C function and cleans up the space for arguments allocated
// by PrepareCallCFunction. The called function is not allowed to trigger a
@@ -1143,7 +1143,8 @@
int num_reg_arguments,
int num_double_arguments);
- void GetCFunctionDoubleResult(const DwVfpRegister dst);
+ void MovFromFloatParameter(DwVfpRegister dst);
+ void MovFromFloatResult(DwVfpRegister dst);
// Calls an API function. Allocates HandleScope, extracts returned value
// from handle and propagates exceptions. Restores context. stack_space
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index f384720..800b5b4 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -2293,9 +2293,9 @@
current = current->next();
}
// Didn't find the extension; fail.
- if (current == NULL) {
- v8::Utils::ReportApiFailure(
- "v8::Context::New()", "Cannot find required extension");
+ if (!Utils::ApiCheck(current != NULL,
+ "v8::Context::New()",
+ "Cannot find required extension")) {
return false;
}
return InstallExtension(isolate, current, extension_states);
@@ -2310,9 +2310,9 @@
if (extension_states->get_state(current) == INSTALLED) return true;
// The current node has already been visited so there must be a
// cycle in the dependency graph; fail.
- if (extension_states->get_state(current) == VISITED) {
- v8::Utils::ReportApiFailure(
- "v8::Context::New()", "Circular extension dependency");
+ if (!Utils::ApiCheck(extension_states->get_state(current) != VISITED,
+ "v8::Context::New()",
+ "Circular extension dependency")) {
return false;
}
ASSERT(extension_states->get_state(current) == UNVISITED);
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
index 67f9dc8..785b9ca 100644
--- a/src/code-stubs-hydrogen.cc
+++ b/src/code-stubs-hydrogen.cc
@@ -491,20 +491,16 @@
AllocationSite::kNestedSiteOffset),
graph()->GetConstant0());
- // Pretenuring calculation fields.
+ // Pretenuring calculation field.
Add<HStoreNamedField>(object,
HObjectAccess::ForAllocationSiteOffset(
- AllocationSite::kMementoFoundCountOffset),
+ AllocationSite::kPretenureDataOffset),
graph()->GetConstant0());
+ // Pretenuring memento creation count field.
Add<HStoreNamedField>(object,
HObjectAccess::ForAllocationSiteOffset(
- AllocationSite::kMementoCreateCountOffset),
- graph()->GetConstant0());
-
- Add<HStoreNamedField>(object,
- HObjectAccess::ForAllocationSiteOffset(
- AllocationSite::kPretenureDecisionOffset),
+ AllocationSite::kPretenureCreateCountOffset),
graph()->GetConstant0());
// Store an empty fixed array for the code dependency.
diff --git a/src/extensions/gc-extension.cc b/src/extensions/gc-extension.cc
index 69fd717..205587f 100644
--- a/src/extensions/gc-extension.cc
+++ b/src/extensions/gc-extension.cc
@@ -42,9 +42,11 @@
void GCExtension::GC(const v8::FunctionCallbackInfo<v8::Value>& args) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate());
if (args[0]->BooleanValue()) {
- isolate->heap()->CollectGarbage(NEW_SPACE, "gc extension");
+ isolate->heap()->CollectGarbage(
+ NEW_SPACE, "gc extension", v8::kGCCallbackFlagForced);
} else {
- isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "gc extension");
+ isolate->heap()->CollectAllGarbage(
+ Heap::kNoGCFlags, "gc extension", v8::kGCCallbackFlagForced);
}
}
diff --git a/src/handles.cc b/src/handles.cc
index bc8d2d7..b3282fa 100644
--- a/src/handles.cc
+++ b/src/handles.cc
@@ -63,9 +63,9 @@
ASSERT(result == current->limit);
// Make sure there's at least one scope on the stack and that the
// top of the scope stack isn't a barrier.
- if (current->level == 0) {
- Utils::ReportApiFailure("v8::HandleScope::CreateHandle()",
- "Cannot create a handle without a HandleScope");
+ if (!Utils::ApiCheck(current->level != 0,
+ "v8::HandleScope::CreateHandle()",
+ "Cannot create a handle without a HandleScope")) {
return NULL;
}
HandleScopeImplementer* impl = isolate->handle_scope_implementer();
diff --git a/src/heap-inl.h b/src/heap-inl.h
index 5e6fb2b..f70b6f7 100644
--- a/src/heap-inl.h
+++ b/src/heap-inl.h
@@ -485,22 +485,32 @@
void Heap::UpdateAllocationSiteFeedback(HeapObject* object) {
Heap* heap = object->GetHeap();
- if (FLAG_allocation_site_pretenuring &&
- heap->new_space_high_promotion_mode_active_ &&
- AllocationSite::CanTrack(object->map()->instance_type())) {
- AllocationMemento* memento = AllocationMemento::FindForHeapObject(
- object, heap, true);
- if (memento != NULL) {
- ASSERT(memento->IsValid());
- bool add_to_scratchpad =
- memento->GetAllocationSite()->IncrementMementoFoundCount();
- if (add_to_scratchpad && heap->allocation_sites_scratchpad_length <
- kAllocationSiteScratchpadSize) {
- heap->allocation_sites_scratchpad[
- heap->allocation_sites_scratchpad_length++] =
- memento->GetAllocationSite();
- }
- }
+ ASSERT(heap->InNewSpace(object));
+
+ if (!FLAG_allocation_site_pretenuring ||
+ !heap->new_space_high_promotion_mode_active_ ||
+ !AllocationSite::CanTrack(object->map()->instance_type())) return;
+
+ // Either object is the last object in the from space, or there is another
+ // object of at least word size (the header map word) following it, so
+ // suffices to compare ptr and top here.
+ Address ptr = object->address() + object->Size();
+ Address top = heap->new_space()->FromSpacePageHigh();
+ ASSERT(ptr == top || ptr + HeapObject::kHeaderSize <= top);
+ if (ptr == top) return;
+
+ HeapObject* candidate = HeapObject::FromAddress(ptr);
+ if (candidate->map() != heap->allocation_memento_map()) return;
+
+ AllocationMemento* memento = AllocationMemento::cast(candidate);
+ if (!memento->IsValid()) return;
+
+ if (memento->GetAllocationSite()->IncrementMementoFoundCount() &&
+ heap->allocation_sites_scratchpad_length <
+ kAllocationSiteScratchpadSize) {
+ heap->allocation_sites_scratchpad[
+ heap->allocation_sites_scratchpad_length++] =
+ memento->GetAllocationSite();
}
}
@@ -532,10 +542,13 @@
}
-bool Heap::CollectGarbage(AllocationSpace space, const char* gc_reason) {
+bool Heap::CollectGarbage(AllocationSpace space,
+ const char* gc_reason,
+ const v8::GCCallbackFlags callbackFlags) {
const char* collector_reason = NULL;
GarbageCollector collector = SelectGarbageCollector(space, &collector_reason);
- return CollectGarbage(space, collector, gc_reason, collector_reason);
+ return CollectGarbage(
+ space, collector, gc_reason, collector_reason, callbackFlags);
}
diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc
index 3125a26..35cfcb4 100644
--- a/src/heap-snapshot-generator.cc
+++ b/src/heap-snapshot-generator.cc
@@ -1403,15 +1403,12 @@
AllocationSite::kTransitionInfoOffset);
SetInternalReference(site, entry, "nested_site", site->nested_site(),
AllocationSite::kNestedSiteOffset);
- SetInternalReference(site, entry, "memento_found_count",
- site->memento_found_count(),
- AllocationSite::kMementoFoundCountOffset);
- SetInternalReference(site, entry, "memento_create_count",
- site->memento_create_count(),
- AllocationSite::kMementoCreateCountOffset);
- SetInternalReference(site, entry, "pretenure_decision",
- site->pretenure_decision(),
- AllocationSite::kPretenureDecisionOffset);
+ SetInternalReference(site, entry, "pretenure_data",
+ site->pretenure_data(),
+ AllocationSite::kPretenureDataOffset);
+ SetInternalReference(site, entry, "pretenure_create_count",
+ site->pretenure_create_count(),
+ AllocationSite::kPretenureCreateCountOffset);
SetInternalReference(site, entry, "dependent_code", site->dependent_code(),
AllocationSite::kDependentCodeOffset);
}
@@ -2131,7 +2128,7 @@
group->info = NULL; // Acquire info object ownership.
}
isolate->global_handles()->RemoveObjectGroups();
- isolate->heap()->CallGCEpilogueCallbacks(major_gc_type);
+ isolate->heap()->CallGCEpilogueCallbacks(major_gc_type, kNoGCCallbackFlags);
// Record objects that are not in ObjectGroups, but have class ID.
GlobalHandlesExtractor extractor(this);
isolate->global_handles()->IterateAllRootsWithClassIds(&extractor);
diff --git a/src/heap.cc b/src/heap.cc
index 60b425c..899d701 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -526,8 +526,8 @@
list_element->IsAllocationSite()) {
AllocationSite* site = use_scratchpad ?
allocation_sites_scratchpad[i] : AllocationSite::cast(list_element);
- allocation_mementos_found += site->memento_found_count()->value();
- if (site->memento_found_count()->value() > 0) {
+ allocation_mementos_found += site->memento_found_count();
+ if (site->memento_found_count() > 0) {
active_allocation_sites++;
}
if (site->DigestPretenuringFeedback()) {
@@ -702,12 +702,14 @@
}
-void Heap::CollectAllGarbage(int flags, const char* gc_reason) {
+void Heap::CollectAllGarbage(int flags,
+ const char* gc_reason,
+ const v8::GCCallbackFlags gc_callback_flags) {
// Since we are ignoring the return value, the exact choice of space does
// not matter, so long as we do not specify NEW_SPACE, which would not
// cause a full GC.
mark_compact_collector_.SetFlags(flags);
- CollectGarbage(OLD_POINTER_SPACE, gc_reason);
+ CollectGarbage(OLD_POINTER_SPACE, gc_reason, gc_callback_flags);
mark_compact_collector_.SetFlags(kNoGCFlags);
}
@@ -750,7 +752,8 @@
bool Heap::CollectGarbage(AllocationSpace space,
GarbageCollector collector,
const char* gc_reason,
- const char* collector_reason) {
+ const char* collector_reason,
+ const v8::GCCallbackFlags gc_callback_flags) {
// The VM is in the GC state until exiting this function.
VMState<GC> state(isolate_);
@@ -805,7 +808,7 @@
(collector == SCAVENGER) ? isolate_->counters()->gc_scavenger()
: isolate_->counters()->gc_compactor());
next_gc_likely_to_collect_more =
- PerformGarbageCollection(collector, &tracer);
+ PerformGarbageCollection(collector, &tracer, gc_callback_flags);
}
GarbageCollectionEpilogue();
@@ -1032,8 +1035,10 @@
survival_rate_ = survival_rate;
}
-bool Heap::PerformGarbageCollection(GarbageCollector collector,
- GCTracer* tracer) {
+bool Heap::PerformGarbageCollection(
+ GarbageCollector collector,
+ GCTracer* tracer,
+ const v8::GCCallbackFlags gc_callback_flags) {
bool next_gc_likely_to_collect_more = false;
if (collector != SCAVENGER) {
@@ -1164,7 +1169,7 @@
GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL);
VMState<EXTERNAL> state(isolate_);
HandleScope handle_scope(isolate_);
- CallGCEpilogueCallbacks(gc_type);
+ CallGCEpilogueCallbacks(gc_type, gc_callback_flags);
}
#ifdef VERIFY_HEAP
@@ -1194,18 +1199,19 @@
}
-void Heap::CallGCEpilogueCallbacks(GCType gc_type) {
+void Heap::CallGCEpilogueCallbacks(GCType gc_type,
+ GCCallbackFlags gc_callback_flags) {
for (int i = 0; i < gc_epilogue_callbacks_.length(); ++i) {
if (gc_type & gc_epilogue_callbacks_[i].gc_type) {
if (!gc_epilogue_callbacks_[i].pass_isolate_) {
v8::GCPrologueCallback callback =
reinterpret_cast<v8::GCPrologueCallback>(
gc_epilogue_callbacks_[i].callback);
- callback(gc_type, kNoGCCallbackFlags);
+ callback(gc_type, gc_callback_flags);
} else {
v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this->isolate());
gc_epilogue_callbacks_[i].callback(
- isolate, gc_type, kNoGCCallbackFlags);
+ isolate, gc_type, gc_callback_flags);
}
}
}
diff --git a/src/heap.h b/src/heap.h
index 7134f06..19d91a9 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -1157,8 +1157,10 @@
// Performs garbage collection operation.
// Returns whether there is a chance that another major GC could
// collect more garbage.
- inline bool CollectGarbage(AllocationSpace space,
- const char* gc_reason = NULL);
+ inline bool CollectGarbage(
+ AllocationSpace space,
+ const char* gc_reason = NULL,
+ const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags);
static const int kNoGCFlags = 0;
static const int kSweepPreciselyMask = 1;
@@ -1173,7 +1175,10 @@
// Performs a full garbage collection. If (flags & kMakeHeapIterableMask) is
// non-zero, then the slower precise sweeper is used, which leaves the heap
// in a state where we can iterate over the heap visiting all objects.
- void CollectAllGarbage(int flags, const char* gc_reason = NULL);
+ void CollectAllGarbage(
+ int flags,
+ const char* gc_reason = NULL,
+ const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags);
// Last hope GC, should try to squeeze as much as possible.
void CollectAllAvailableGarbage(const char* gc_reason = NULL);
@@ -1701,7 +1706,7 @@
inline Isolate* isolate();
void CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags);
- void CallGCEpilogueCallbacks(GCType gc_type);
+ void CallGCEpilogueCallbacks(GCType gc_type, GCCallbackFlags flags);
inline bool OldGenerationAllocationLimitReached();
@@ -2052,16 +2057,20 @@
// Performs garbage collection operation.
// Returns whether there is a chance that another major GC could
// collect more garbage.
- bool CollectGarbage(AllocationSpace space,
- GarbageCollector collector,
- const char* gc_reason,
- const char* collector_reason);
+ bool CollectGarbage(
+ AllocationSpace space,
+ GarbageCollector collector,
+ const char* gc_reason,
+ const char* collector_reason,
+ const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags);
// Performs garbage collection
// Returns whether there is a chance another major GC could
// collect more garbage.
- bool PerformGarbageCollection(GarbageCollector collector,
- GCTracer* tracer);
+ bool PerformGarbageCollection(
+ GarbageCollector collector,
+ GCTracer* tracer,
+ const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags);
inline void UpdateOldSpaceLimits();
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 4991668..4e614d8 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -4284,11 +4284,9 @@
return HObjectAccess(kInobject, offset, Representation::Tagged());
case AllocationSite::kNestedSiteOffset:
return HObjectAccess(kInobject, offset, Representation::Tagged());
- case AllocationSite::kMementoFoundCountOffset:
+ case AllocationSite::kPretenureDataOffset:
return HObjectAccess(kInobject, offset, Representation::Smi());
- case AllocationSite::kMementoCreateCountOffset:
- return HObjectAccess(kInobject, offset, Representation::Smi());
- case AllocationSite::kPretenureDecisionOffset:
+ case AllocationSite::kPretenureCreateCountOffset:
return HObjectAccess(kInobject, offset, Representation::Smi());
case AllocationSite::kDependentCodeOffset:
return HObjectAccess(kInobject, offset, Representation::Tagged());
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 7c6b2cb..4377b42 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -2642,7 +2642,7 @@
if (FLAG_allocation_site_pretenuring) {
HValue* memento_create_count = Add<HLoadNamedField>(
allocation_site, HObjectAccess::ForAllocationSiteOffset(
- AllocationSite::kMementoCreateCountOffset));
+ AllocationSite::kPretenureCreateCountOffset));
memento_create_count = AddUncasted<HAdd>(
memento_create_count, graph()->GetConstant1());
// This smi value is reset to zero after every gc, overflow isn't a problem
@@ -2650,7 +2650,7 @@
memento_create_count->ClearFlag(HValue::kCanOverflow);
HStoreNamedField* store = Add<HStoreNamedField>(
allocation_site, HObjectAccess::ForAllocationSiteOffset(
- AllocationSite::kMementoCreateCountOffset), memento_create_count);
+ AllocationSite::kPretenureCreateCountOffset), memento_create_count);
// No write barrier needed to store a smi.
store->SkipWriteBarrier();
}
@@ -7613,11 +7613,12 @@
HValue* function = Top();
AddCheckConstantFunction(expr->holder(), function, function_map);
- Drop(1);
CHECK_ALIVE_OR_RETURN(VisitForValue(args->at(0)), true);
HValue* receiver = Pop();
+ Drop(1); // Pop the function.
+
if (function_state()->outer() == NULL) {
HInstruction* elements = Add<HArgumentsElements>(false);
HInstruction* length = Add<HArgumentsLength>(elements);
@@ -7906,10 +7907,11 @@
ElementsKind kind = expr->elements_kind();
Handle<Cell> cell = expr->allocation_info_cell();
- AllocationSite* site = AllocationSite::cast(cell->value());
+ Handle<AllocationSite> site(AllocationSite::cast(cell->value()));
// Register on the site for deoptimization if the cell value changes.
- site->AddDependentCompilationInfo(AllocationSite::TRANSITIONS, top_info());
+ AllocationSite::AddDependentCompilationInfo(
+ site, AllocationSite::TRANSITIONS, top_info());
HInstruction* cell_instruction = Add<HConstant>(cell);
// In the single constant argument case, we may have to adjust elements kind
@@ -8924,8 +8926,9 @@
// Register the dependent code with the allocation site.
if (!allocation_mode.feedback_site().is_null()) {
ASSERT(!graph()->info()->IsStub());
- allocation_mode.feedback_site()->AddDependentCompilationInfo(
- AllocationSite::TENURING, top_info());
+ Handle<AllocationSite> site(allocation_mode.feedback_site());
+ AllocationSite::AddDependentCompilationInfo(
+ site, AllocationSite::TENURING, top_info());
}
// Inline string addition if we know that we'll create a cons string.
@@ -9501,8 +9504,9 @@
PretenureFlag pretenure_flag = isolate()->heap()->GetPretenureMode();
if (FLAG_allocation_site_pretenuring) {
pretenure_flag = site_context->current()->GetPretenureMode();
- site_context->current()->AddDependentCompilationInfo(
- AllocationSite::TENURING, top_info());
+ Handle<AllocationSite> site(site_context->current());
+ AllocationSite::AddDependentCompilationInfo(
+ site, AllocationSite::TENURING, top_info());
}
HInstruction* object = Add<HAllocate>(object_size_constant, type,
@@ -10716,10 +10720,21 @@
}
PrintEmptyProperty("xhandlers");
- const char* flags = current->IsLoopSuccessorDominator()
- ? "dom-loop-succ"
- : "";
- PrintStringProperty("flags", flags);
+
+ {
+ PrintIndent();
+ trace_.Add("flags");
+ if (current->IsLoopSuccessorDominator()) {
+ trace_.Add(" \"dom-loop-succ\"");
+ }
+ if (current->IsUnreachable()) {
+ trace_.Add(" \"dead\"");
+ }
+ if (current->is_osr_entry()) {
+ trace_.Add(" \"osr\"");
+ }
+ trace_.Add("\n");
+ }
if (current->dominator() != NULL) {
PrintBlockProperty("dominator", current->dominator()->block_id());
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index 933cf43..66c72f8 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -1425,13 +1425,13 @@
{
AllowExternalCallThatCantCauseGC scope(masm);
__ PrepareCallCFunction(0, 2, scratch2);
- __ SetCallCDoubleArguments(double_base, double_exponent);
+ __ MovToFloatParameters(double_base, double_exponent);
__ CallCFunction(
ExternalReference::power_double_double_function(masm->isolate()),
0, 2);
}
__ pop(ra);
- __ GetCFunctionDoubleResult(double_result);
+ __ MovFromFloatResult(double_result);
__ jmp(&done);
__ bind(&int_exponent_convert);
@@ -1509,13 +1509,13 @@
{
AllowExternalCallThatCantCauseGC scope(masm);
__ PrepareCallCFunction(0, 2, scratch);
- __ SetCallCDoubleArguments(double_base, double_exponent);
+ __ MovToFloatParameters(double_base, double_exponent);
__ CallCFunction(
ExternalReference::power_double_double_function(masm->isolate()),
0, 2);
}
__ pop(ra);
- __ GetCFunctionDoubleResult(double_result);
+ __ MovFromFloatResult(double_result);
__ bind(&done);
__ IncrementCounter(counters->math_pow(), 1, scratch, scratch2);
diff --git a/src/mips/codegen-mips.cc b/src/mips/codegen-mips.cc
index d07a6bb..0dd42d6 100644
--- a/src/mips/codegen-mips.cc
+++ b/src/mips/codegen-mips.cc
@@ -535,9 +535,9 @@
MacroAssembler masm(NULL, buffer, static_cast<int>(actual_size));
- __ GetFromCDoubleArguments(f12);
+ __ MovFromFloatParameter(f12);
__ sqrt_d(f0, f12);
- __ SetForCDoubleResult(f0);
+ __ MovToFloatResult(f0);
__ Ret();
CodeDesc desc;
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index ddd5037..ac8c04a 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -1936,12 +1936,12 @@
__ MultiPush(saved_regs);
__ PrepareCallCFunction(0, 2, scratch0());
- __ SetCallCDoubleArguments(left, right);
+ __ MovToFloatParameters(left, right);
__ CallCFunction(
ExternalReference::mod_two_doubles_operation(isolate()),
0, 2);
// Move the result in the double result register.
- __ GetCFunctionDoubleResult(result);
+ __ MovFromFloatResult(result);
// Restore saved register.
__ MultiPop(saved_regs);
@@ -3856,10 +3856,10 @@
void LCodeGen::DoMathLog(LMathLog* instr) {
__ PrepareCallCFunction(0, 1, scratch0());
- __ SetCallCDoubleArguments(ToDoubleRegister(instr->value()));
+ __ MovToFloatParameter(ToDoubleRegister(instr->value()));
__ CallCFunction(ExternalReference::math_log_double_function(isolate()),
0, 1);
- __ GetCFunctionDoubleResult(ToDoubleRegister(instr->result()));
+ __ MovFromFloatResult(ToDoubleRegister(instr->result()));
}
diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc
index 116cb05..c64fe2a 100644
--- a/src/mips/macro-assembler-mips.cc
+++ b/src/mips/macro-assembler-mips.cc
@@ -3517,7 +3517,7 @@
}
-void MacroAssembler::GetCFunctionDoubleResult(const DoubleRegister dst) {
+void MacroAssembler::MovFromFloatResult(DoubleRegister dst) {
if (IsMipsSoftFloatABI) {
Move(dst, v0, v1);
} else {
@@ -3526,7 +3526,7 @@
}
-void MacroAssembler::GetFromCDoubleArguments(const DoubleRegister dst) {
+void MacroAssembler::MovFromFloatParameter(DoubleRegister dst) {
if (IsMipsSoftFloatABI) {
Move(dst, a0, a1);
} else {
@@ -3535,50 +3535,38 @@
}
-void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg) {
+void MacroAssembler::MovToFloatParameter(DoubleRegister src) {
if (!IsMipsSoftFloatABI) {
- Move(f12, dreg);
+ Move(f12, src);
} else {
- Move(a0, a1, dreg);
+ Move(a0, a1, src);
}
}
-void MacroAssembler::SetForCDoubleResult(DoubleRegister dreg) {
+void MacroAssembler::MovToFloatResult(DoubleRegister src) {
if (!IsMipsSoftFloatABI) {
- Move(f0, dreg);
+ Move(f0, src);
} else {
- Move(v0, v1, dreg);
+ Move(v0, v1, src);
}
}
-void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg1,
- DoubleRegister dreg2) {
+void MacroAssembler::MovToFloatParameters(DoubleRegister src1,
+ DoubleRegister src2) {
if (!IsMipsSoftFloatABI) {
- if (dreg2.is(f12)) {
- ASSERT(!dreg1.is(f14));
- Move(f14, dreg2);
- Move(f12, dreg1);
+ if (src2.is(f12)) {
+ ASSERT(!src1.is(f14));
+ Move(f14, src2);
+ Move(f12, src1);
} else {
- Move(f12, dreg1);
- Move(f14, dreg2);
+ Move(f12, src1);
+ Move(f14, src2);
}
} else {
- Move(a0, a1, dreg1);
- Move(a2, a3, dreg2);
- }
-}
-
-
-void MacroAssembler::SetCallCDoubleArguments(DoubleRegister dreg,
- Register reg) {
- if (!IsMipsSoftFloatABI) {
- Move(f12, dreg);
- Move(a2, reg);
- } else {
- Move(a2, reg);
- Move(a0, a1, dreg);
+ Move(a0, a1, src1);
+ Move(a2, a3, src2);
}
}
diff --git a/src/mips/macro-assembler-mips.h b/src/mips/macro-assembler-mips.h
index c3f265f..8fc5d9d 100644
--- a/src/mips/macro-assembler-mips.h
+++ b/src/mips/macro-assembler-mips.h
@@ -1277,17 +1277,16 @@
void CallCFunction(Register function,
int num_reg_arguments,
int num_double_arguments);
- void GetCFunctionDoubleResult(const DoubleRegister dst);
- void GetFromCDoubleArguments(const DoubleRegister dst);
+ void MovFromFloatResult(DoubleRegister dst);
+ void MovFromFloatParameter(DoubleRegister dst);
// There are two ways of passing double arguments on MIPS, depending on
// whether soft or hard floating point ABI is used. These functions
// abstract parameter passing for the three different ways we call
// C functions from generated code.
- void SetCallCDoubleArguments(DoubleRegister dreg);
- void SetCallCDoubleArguments(DoubleRegister dreg1, DoubleRegister dreg2);
- void SetCallCDoubleArguments(DoubleRegister dreg, Register reg);
- void SetForCDoubleResult(DoubleRegister dreg);
+ void MovToFloatParameter(DoubleRegister src);
+ void MovToFloatParameters(DoubleRegister src1, DoubleRegister src2);
+ void MovToFloatResult(DoubleRegister src);
// Calls an API function. Allocates HandleScope, extracts returned value
// from handle and propagates exceptions. Restores context. stack_space
diff --git a/src/objects-inl.h b/src/objects-inl.h
index bcfb598..49e4d69 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -48,6 +48,7 @@
#include "factory.h"
#include "incremental-marking.h"
#include "transitions-inl.h"
+#include "objects-visiting.h"
namespace v8 {
namespace internal {
@@ -1304,9 +1305,8 @@
set_transition_info(Smi::FromInt(0));
SetElementsKind(GetInitialFastElementsKind());
set_nested_site(Smi::FromInt(0));
- set_memento_create_count(Smi::FromInt(0));
- set_memento_found_count(Smi::FromInt(0));
- set_pretenure_decision(Smi::FromInt(0));
+ set_pretenure_data(Smi::FromInt(0));
+ set_pretenure_create_count(Smi::FromInt(0));
set_dependent_code(DependentCode::cast(GetHeap()->empty_fixed_array()),
SKIP_WRITE_BARRIER);
}
@@ -1315,7 +1315,7 @@
void AllocationSite::MarkZombie() {
ASSERT(!IsZombie());
Initialize();
- set_pretenure_decision(Smi::FromInt(kZombie));
+ set_pretenure_decision(kZombie);
}
@@ -1367,35 +1367,50 @@
}
+inline void AllocationSite::set_memento_found_count(int count) {
+ int value = pretenure_data()->value();
+ // Verify that we can count more mementos than we can possibly find in one
+ // new space collection.
+ ASSERT((GetHeap()->MaxSemiSpaceSize() /
+ (StaticVisitorBase::kMinObjectSizeInWords * kPointerSize +
+ AllocationMemento::kSize)) < MementoFoundCountBits::kMax);
+ ASSERT(count < MementoFoundCountBits::kMax);
+ set_pretenure_data(
+ Smi::FromInt(MementoFoundCountBits::update(value, count)),
+ SKIP_WRITE_BARRIER);
+}
+
inline bool AllocationSite::IncrementMementoFoundCount() {
if (IsZombie()) return false;
- int value = memento_found_count()->value();
- set_memento_found_count(Smi::FromInt(value + 1));
+ int value = memento_found_count();
+ set_memento_found_count(value + 1);
return value == 0;
}
inline void AllocationSite::IncrementMementoCreateCount() {
ASSERT(FLAG_allocation_site_pretenuring);
- int value = memento_create_count()->value();
- set_memento_create_count(Smi::FromInt(value + 1));
+ int value = memento_create_count();
+ set_memento_create_count(value + 1);
}
inline bool AllocationSite::DigestPretenuringFeedback() {
bool decision_made = false;
- int create_count = memento_create_count()->value();
+ int create_count = memento_create_count();
if (create_count >= kPretenureMinimumCreated) {
- int found_count = memento_found_count()->value();
+ int found_count = memento_found_count();
double ratio = static_cast<double>(found_count) / create_count;
if (FLAG_trace_track_allocation_sites) {
PrintF("AllocationSite: %p (created, found, ratio) (%d, %d, %f)\n",
static_cast<void*>(this), create_count, found_count, ratio);
}
int current_mode = GetPretenureMode();
- int result = ratio >= kPretenureRatio ? kTenure : kDontTenure;
- set_pretenure_decision(Smi::FromInt(result));
+ PretenureDecision result = ratio >= kPretenureRatio
+ ? kTenure
+ : kDontTenure;
+ set_pretenure_decision(result);
decision_made = true;
if (current_mode != GetPretenureMode()) {
dependent_code()->DeoptimizeDependentCodeGroup(
@@ -1405,8 +1420,8 @@
}
// Clear feedback calculation fields until the next gc.
- set_memento_found_count(Smi::FromInt(0));
- set_memento_create_count(Smi::FromInt(0));
+ set_memento_found_count(0);
+ set_memento_create_count(0);
return decision_made;
}
@@ -4600,10 +4615,9 @@
ACCESSORS(AllocationSite, transition_info, Object, kTransitionInfoOffset)
ACCESSORS(AllocationSite, nested_site, Object, kNestedSiteOffset)
-ACCESSORS_TO_SMI(AllocationSite, memento_found_count, kMementoFoundCountOffset)
-ACCESSORS_TO_SMI(AllocationSite, memento_create_count,
- kMementoCreateCountOffset)
-ACCESSORS_TO_SMI(AllocationSite, pretenure_decision, kPretenureDecisionOffset)
+ACCESSORS_TO_SMI(AllocationSite, pretenure_data, kPretenureDataOffset)
+ACCESSORS_TO_SMI(AllocationSite, pretenure_create_count,
+ kPretenureCreateCountOffset)
ACCESSORS(AllocationSite, dependent_code, DependentCode,
kDependentCodeOffset)
ACCESSORS(AllocationSite, weak_next, Object, kWeakNextOffset)
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
index 1da9852..219b692 100644
--- a/src/objects-printer.cc
+++ b/src/objects-printer.cc
@@ -1136,11 +1136,11 @@
PrintF(out, "\n - nested site: ");
nested_site()->ShortPrint(out);
PrintF(out, "\n - memento found count: ");
- memento_found_count()->ShortPrint(out);
+ Smi::FromInt(memento_found_count())->ShortPrint(out);
PrintF(out, "\n - memento create count: ");
- memento_create_count()->ShortPrint(out);
+ Smi::FromInt(memento_create_count())->ShortPrint(out);
PrintF(out, "\n - pretenure decision: ");
- pretenure_decision()->ShortPrint(out);
+ Smi::FromInt(pretenure_decision())->ShortPrint(out);
PrintF(out, "\n - transition_info: ");
if (transition_info()->IsSmi()) {
ElementsKind kind = GetElementsKind();
diff --git a/src/objects.cc b/src/objects.cc
index 539d4af..23cd6d9 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -45,7 +45,6 @@
#include "isolate-inl.h"
#include "log.h"
#include "objects-inl.h"
-#include "objects-visiting.h"
#include "objects-visiting-inl.h"
#include "macro-assembler.h"
#include "mark-compact.h"
@@ -9202,39 +9201,6 @@
}
-AllocationMemento* AllocationMemento::FindForHeapObject(HeapObject* object,
- Heap* heap,
- bool in_GC) {
- // AllocationMemento objects are only allocated immediately after objects in
- // NewSpace. Detecting whether a memento is present involves carefully
- // checking the object immediately after the current object (if there is one)
- // to see if it's an AllocationMemento.
- ASSERT(heap->InNewSpace(object));
- Address ptr_end = (reinterpret_cast<Address>(object) - kHeapObjectTag) +
- object->Size();
- Address top;
- if (in_GC) {
- top = heap->new_space()->FromSpacePageHigh();
- } else {
- top = heap->NewSpaceTop();
- }
- if ((ptr_end + AllocationMemento::kSize) <= top) {
- // There is room in newspace for allocation info. Do we have some?
- Map** possible_allocation_memento_map =
- reinterpret_cast<Map**>(ptr_end);
- if (*possible_allocation_memento_map ==
- object->GetHeap()->allocation_memento_map()) {
- AllocationMemento* memento = AllocationMemento::cast(
- reinterpret_cast<Object*>(ptr_end + kHeapObjectTag));
- if (memento->IsValid()) {
- return memento;
- }
- }
- }
- return NULL;
-}
-
-
uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
// For array indexes mix the length into the hash as an array index could
// be zero.
@@ -12797,14 +12763,14 @@
dependent_code()->DeoptimizeDependentCodeGroup(
GetIsolate(),
DependentCode::kAllocationSiteTenuringChangedGroup);
- set_pretenure_decision(Smi::FromInt(kUndecided));
- set_memento_found_count(Smi::FromInt(0));
- set_memento_create_count(Smi::FromInt(0));
+ set_pretenure_decision(kUndecided);
+ set_memento_found_count(0);
+ set_memento_create_count(0);
}
PretenureFlag AllocationSite::GetPretenureMode() {
- int mode = pretenure_decision()->value();
+ PretenureDecision mode = pretenure_decision();
// Zombie objects "decide" to be untenured.
return (mode == kTenure && GetHeap()->GetPretenureMode() == TENURED)
? TENURED : NOT_TENURED;
@@ -12878,22 +12844,16 @@
}
-void AllocationSite::AddDependentCompilationInfo(Reason reason,
+// static
+void AllocationSite::AddDependentCompilationInfo(Handle<AllocationSite> site,
+ Reason reason,
CompilationInfo* info) {
- DependentCode::DependencyGroup group = ToDependencyGroup(reason);
- Handle<DependentCode> dep(dependent_code());
+ DependentCode::DependencyGroup group = site->ToDependencyGroup(reason);
+ Handle<DependentCode> dep(site->dependent_code());
Handle<DependentCode> codes =
DependentCode::Insert(dep, group, info->object_wrapper());
- if (*codes != dependent_code()) set_dependent_code(*codes);
- info->dependencies(group)->Add(Handle<HeapObject>(this), info->zone());
-}
-
-
-void AllocationSite::AddDependentCode(Reason reason, Handle<Code> code) {
- DependentCode::DependencyGroup group = ToDependencyGroup(reason);
- Handle<DependentCode> codes = DependentCode::Insert(
- Handle<DependentCode>(dependent_code()), group, code);
- if (*codes != dependent_code()) set_dependent_code(*codes);
+ if (*codes != site->dependent_code()) site->set_dependent_code(*codes);
+ info->dependencies(group)->Add(Handle<HeapObject>(*site), info->zone());
}
@@ -12905,17 +12865,24 @@
MaybeObject* JSObject::UpdateAllocationSite(ElementsKind to_kind) {
- if (!IsJSArray()) {
- return this;
- }
+ if (!IsJSArray()) return this;
Heap* heap = GetHeap();
if (!heap->InNewSpace(this)) return this;
- AllocationMemento* memento = AllocationMemento::FindForHeapObject(this, heap);
- if (memento == NULL || !memento->IsValid()) {
- return this;
- }
+ // Either object is the last object in the new space, or there is another
+ // object of at least word size (the header map word) following it, so
+ // suffices to compare ptr and top here.
+ Address ptr = address() + JSArray::kSize;
+ Address top = heap->NewSpaceTop();
+ ASSERT(ptr == top || ptr + HeapObject::kHeaderSize <= top);
+ if (ptr == top) return this;
+
+ HeapObject* candidate = HeapObject::FromAddress(ptr);
+ if (candidate->map() != heap->allocation_memento_map()) return this;
+
+ AllocationMemento* memento = AllocationMemento::cast(candidate);
+ if (!memento->IsValid()) return this;
// Walk through to the Allocation Site
AllocationSite* site = memento->GetAllocationSite();
@@ -16663,14 +16630,6 @@
}
-void PropertyCell::AddDependentCode(Handle<Code> code) {
- Handle<DependentCode> codes = DependentCode::Insert(
- Handle<DependentCode>(dependent_code()),
- DependentCode::kPropertyCellChangedGroup, code);
- if (*codes != dependent_code()) set_dependent_code(*codes);
-}
-
-
const char* GetBailoutReason(BailoutReason reason) {
ASSERT(reason < kLastErrorMessage);
#define ERROR_MESSAGES_TEXTS(C, T) T,
diff --git a/src/objects.h b/src/objects.h
index 1dc54b2..cdf1e24 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -8125,11 +8125,12 @@
static const int kPretenureMinimumCreated = 100;
// Values for pretenure decision field.
- enum {
+ enum PretenureDecision {
kUndecided = 0,
kDontTenure = 1,
kTenure = 2,
- kZombie = 3
+ kZombie = 3,
+ kLastPretenureDecisionValue = kZombie
};
DECL_ACCESSORS(transition_info, Object)
@@ -8137,11 +8138,8 @@
// walked in a particular order. So [[1, 2], 1, 2] will have one
// nested_site, but [[1, 2], 3, [4]] will have a list of two.
DECL_ACCESSORS(nested_site, Object)
- DECL_ACCESSORS(memento_found_count, Smi)
- DECL_ACCESSORS(memento_create_count, Smi)
- // TODO(mvstanton): we don't need a whole integer to record pretenure
- // decision. Consider sharing space with memento_found_count.
- DECL_ACCESSORS(pretenure_decision, Smi)
+ DECL_ACCESSORS(pretenure_data, Smi)
+ DECL_ACCESSORS(pretenure_create_count, Smi)
DECL_ACCESSORS(dependent_code, DependentCode)
DECL_ACCESSORS(weak_next, Object)
@@ -8150,10 +8148,16 @@
// This method is expensive, it should only be called for reporting.
bool IsNestedSite();
+ // transition_info bitfields, for constructed array transition info.
class ElementsKindBits: public BitField<ElementsKind, 0, 15> {};
class UnusedBits: public BitField<int, 15, 14> {};
class DoNotInlineBit: public BitField<bool, 29, 1> {};
+ // Bitfields for pretenure_data
+ class MementoFoundCountBits: public BitField<int, 0, 28> {};
+ class PretenureDecisionBits: public BitField<PretenureDecision, 28, 2> {};
+ STATIC_ASSERT(PretenureDecisionBits::kMax >= kLastPretenureDecisionValue);
+
// Increments the mementos found counter and returns true when the first
// memento was found for a given allocation site.
inline bool IncrementMementoFoundCount();
@@ -8164,12 +8168,39 @@
void ResetPretenureDecision();
+ PretenureDecision pretenure_decision() {
+ int value = pretenure_data()->value();
+ return PretenureDecisionBits::decode(value);
+ }
+
+ void set_pretenure_decision(PretenureDecision decision) {
+ int value = pretenure_data()->value();
+ set_pretenure_data(
+ Smi::FromInt(PretenureDecisionBits::update(value, decision)),
+ SKIP_WRITE_BARRIER);
+ }
+
+ int memento_found_count() {
+ int value = pretenure_data()->value();
+ return MementoFoundCountBits::decode(value);
+ }
+
+ inline void set_memento_found_count(int count);
+
+ int memento_create_count() {
+ return pretenure_create_count()->value();
+ }
+
+ void set_memento_create_count(int count) {
+ set_pretenure_create_count(Smi::FromInt(count), SKIP_WRITE_BARRIER);
+ }
+
// The pretenuring decision is made during gc, and the zombie state allows
// us to recognize when an allocation site is just being kept alive because
// a later traversal of new space may discover AllocationMementos that point
// to this AllocationSite.
bool IsZombie() {
- return pretenure_decision()->value() == kZombie;
+ return pretenure_decision() == kZombie;
}
inline void MarkZombie();
@@ -8213,8 +8244,9 @@
TRANSITIONS
};
- void AddDependentCompilationInfo(Reason reason, CompilationInfo* info);
- void AddDependentCode(Reason reason, Handle<Code> code);
+ static void AddDependentCompilationInfo(Handle<AllocationSite> site,
+ Reason reason,
+ CompilationInfo* info);
DECLARE_PRINTER(AllocationSite)
DECLARE_VERIFIER(AllocationSite)
@@ -8227,13 +8259,11 @@
static const int kTransitionInfoOffset = HeapObject::kHeaderSize;
static const int kNestedSiteOffset = kTransitionInfoOffset + kPointerSize;
- static const int kMementoFoundCountOffset = kNestedSiteOffset + kPointerSize;
- static const int kMementoCreateCountOffset =
- kMementoFoundCountOffset + kPointerSize;
- static const int kPretenureDecisionOffset =
- kMementoCreateCountOffset + kPointerSize;
+ static const int kPretenureDataOffset = kNestedSiteOffset + kPointerSize;
+ static const int kPretenureCreateCountOffset =
+ kPretenureDataOffset + kPointerSize;
static const int kDependentCodeOffset =
- kPretenureDecisionOffset + kPointerSize;
+ kPretenureCreateCountOffset + kPointerSize;
static const int kWeakNextOffset = kDependentCodeOffset + kPointerSize;
static const int kSize = kWeakNextOffset + kPointerSize;
@@ -8250,7 +8280,7 @@
private:
inline DependentCode::DependencyGroup ToDependencyGroup(Reason reason);
bool PretenuringDecisionMade() {
- return pretenure_decision()->value() != kUndecided;
+ return pretenure_decision() != kUndecided;
}
DISALLOW_IMPLICIT_CONSTRUCTORS(AllocationSite);
@@ -8276,10 +8306,6 @@
DECLARE_PRINTER(AllocationMemento)
DECLARE_VERIFIER(AllocationMemento)
- // Returns NULL if no AllocationMemento is available for object.
- static AllocationMemento* FindForHeapObject(HeapObject* object,
- Heap* heap,
- bool in_GC = false);
static inline AllocationMemento* cast(Object* obj);
private:
diff --git a/src/version.cc b/src/version.cc
index 0e8630b..5066b9a 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
// system so their names cannot be changed without changing the scripts.
#define MAJOR_VERSION 3
#define MINOR_VERSION 24
-#define BUILD_NUMBER 14
+#define BUILD_NUMBER 15
#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
diff --git a/src/zone.cc b/src/zone.cc
index 9ee00ed..417f895 100644
--- a/src/zone.cc
+++ b/src/zone.cc
@@ -185,25 +185,31 @@
// except that we employ a maximum segment size when we delete. This
// is to avoid excessive malloc() and free() overhead.
Segment* head = segment_head_;
- int old_size = (head == NULL) ? 0 : head->size();
- static const int kSegmentOverhead = sizeof(Segment) + kAlignment;
- int new_size_no_overhead = size + (old_size << 1);
- int new_size = kSegmentOverhead + new_size_no_overhead;
+ const size_t old_size = (head == NULL) ? 0 : head->size();
+ static const size_t kSegmentOverhead = sizeof(Segment) + kAlignment;
+ const size_t new_size_no_overhead = size + (old_size << 1);
+ size_t new_size = kSegmentOverhead + new_size_no_overhead;
+ const size_t min_new_size = kSegmentOverhead + static_cast<size_t>(size);
// Guard against integer overflow.
- if (new_size_no_overhead < size || new_size < kSegmentOverhead) {
+ if (new_size_no_overhead < static_cast<size_t>(size) ||
+ new_size < static_cast<size_t>(kSegmentOverhead)) {
V8::FatalProcessOutOfMemory("Zone");
return NULL;
}
- if (new_size < kMinimumSegmentSize) {
+ if (new_size < static_cast<size_t>(kMinimumSegmentSize)) {
new_size = kMinimumSegmentSize;
- } else if (new_size > kMaximumSegmentSize) {
+ } else if (new_size > static_cast<size_t>(kMaximumSegmentSize)) {
// Limit the size of new segments to avoid growing the segment size
// exponentially, thus putting pressure on contiguous virtual address space.
// All the while making sure to allocate a segment large enough to hold the
// requested size.
- new_size = Max(kSegmentOverhead + size, kMaximumSegmentSize);
+ new_size = Max(min_new_size, static_cast<size_t>(kMaximumSegmentSize));
}
- Segment* segment = NewSegment(new_size);
+ if (new_size > INT_MAX) {
+ V8::FatalProcessOutOfMemory("Zone");
+ return NULL;
+ }
+ Segment* segment = NewSegment(static_cast<int>(new_size));
if (segment == NULL) {
V8::FatalProcessOutOfMemory("Zone");
return NULL;
@@ -213,7 +219,10 @@
Address result = RoundUp(segment->start(), kAlignment);
position_ = result + size;
// Check for address overflow.
- if (position_ < result) {
+ // (Should not happen since the segment is guaranteed to accomodate
+ // size bytes + header and alignment padding)
+ if (reinterpret_cast<uintptr_t>(position_)
+ < reinterpret_cast<uintptr_t>(result)) {
V8::FatalProcessOutOfMemory("Zone");
return NULL;
}
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 00465e3..839ddd9 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -14785,9 +14785,10 @@
// a workaround for now to make this test not fail.
v8::V8::Initialize();
v8::Isolate* isolate = CcTest::isolate();
+ HandleScope handle_scope(isolate);
const char* script = "function foo(a) { return a+1; }";
- v8::ScriptData* sd =
- v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
+ v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
+ isolate, script, v8::String::kNormalString, i::StrLength(script)));
CHECK_NE(sd->Length(), 0);
CHECK_NE(sd->Data(), NULL);
CHECK(!sd->HasError());
@@ -14798,9 +14799,10 @@
TEST(PreCompileWithError) {
v8::V8::Initialize();
v8::Isolate* isolate = CcTest::isolate();
+ HandleScope handle_scope(isolate);
const char* script = "function foo(a) { return 1 * * 2; }";
- v8::ScriptData* sd =
- v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
+ v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
+ isolate, script, v8::String::kNormalString, i::StrLength(script)));
CHECK(sd->HasError());
delete sd;
}
@@ -14809,9 +14811,10 @@
TEST(Regress31661) {
v8::V8::Initialize();
v8::Isolate* isolate = CcTest::isolate();
+ HandleScope handle_scope(isolate);
const char* script = " The Definintive Guide";
- v8::ScriptData* sd =
- v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
+ v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
+ isolate, script, v8::String::kNormalString, i::StrLength(script)));
CHECK(sd->HasError());
delete sd;
}
@@ -14821,9 +14824,10 @@
TEST(PreCompileSerialization) {
v8::V8::Initialize();
v8::Isolate* isolate = CcTest::isolate();
+ HandleScope handle_scope(isolate);
const char* script = "function foo(a) { return a+1; }";
- v8::ScriptData* sd =
- v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
+ v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
+ isolate, script, v8::String::kNormalString, i::StrLength(script)));
// Serialize.
int serialized_data_length = sd->Length();
@@ -14866,8 +14870,8 @@
const char* script = "function foo(){ return 5;}\n"
"function bar(){ return 6 + 7;} foo();";
- v8::ScriptData* sd =
- v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
+ v8::ScriptData* sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
+ isolate, script, v8::String::kNormalString, i::StrLength(script)));
CHECK(!sd->HasError());
// ScriptDataImpl private implementation details
const int kHeaderSize = i::PreparseDataConstants::kHeaderSize;
@@ -14893,7 +14897,8 @@
// Overwrite function bar's start position with 200. The function entry
// will not be found when searching for it by position and we should fall
// back on eager compilation.
- sd = v8::ScriptData::PreCompile(isolate, script, i::StrLength(script));
+ sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
+ isolate, script, v8::String::kNormalString, i::StrLength(script)));
sd_data = reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data()));
sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryStartOffset] =
200;
@@ -14904,42 +14909,6 @@
}
-// Verifies that the Handle<String> and const char* versions of the API produce
-// the same results (at least for one trivial case).
-TEST(PreCompileAPIVariationsAreSame) {
- v8::V8::Initialize();
- v8::Isolate* isolate = CcTest::isolate();
- v8::HandleScope scope(isolate);
-
- const char* cstring = "function foo(a) { return a+1; }";
-
- v8::ScriptData* sd_from_cstring =
- v8::ScriptData::PreCompile(isolate, cstring, i::StrLength(cstring));
-
- TestAsciiResource* resource = new TestAsciiResource(cstring);
- v8::ScriptData* sd_from_external_string = v8::ScriptData::PreCompile(
- v8::String::NewExternal(isolate, resource));
-
- v8::ScriptData* sd_from_string = v8::ScriptData::PreCompile(
- v8::String::NewFromUtf8(isolate, cstring));
-
- CHECK_EQ(sd_from_cstring->Length(), sd_from_external_string->Length());
- CHECK_EQ(0, memcmp(sd_from_cstring->Data(),
- sd_from_external_string->Data(),
- sd_from_cstring->Length()));
-
- CHECK_EQ(sd_from_cstring->Length(), sd_from_string->Length());
- CHECK_EQ(0, memcmp(sd_from_cstring->Data(),
- sd_from_string->Data(),
- sd_from_cstring->Length()));
-
-
- delete sd_from_cstring;
- delete sd_from_external_string;
- delete sd_from_string;
-}
-
-
// This tests that we do not allow dictionary load/call inline caches
// to use functions that have not yet been compiled. The potential
// problem of loading a function that has not yet been compiled can
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index d5fae58..493cbd3 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -2240,7 +2240,7 @@
CcTest::heap()->SetNewSpaceHighPromotionModeActive(true);
v8::Local<v8::Value> res = CompileRun(
- "var number_elements = 3000;"
+ "var number_elements = 30000;"
"var elements = new Array(number_elements);"
"function DataObject() {"
" this.a = [{}];"
@@ -2345,7 +2345,7 @@
v8::HandleScope scope(CcTest::isolate());
v8::Local<v8::Value> res = CompileRun(
- "var number_elements = 20000;"
+ "var number_elements = 30000;"
"var elements = new Array(number_elements);"
"function f() {"
" for (var i = 0; i < number_elements; i++) {"
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
index e53250d..8fbd60d 100644
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -108,6 +108,7 @@
TEST(ScanHTMLEndComments) {
v8::V8::Initialize();
v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope handles(isolate);
// Regression test. See:
// http://code.google.com/p/chromium/issues/detail?id=53548
@@ -144,15 +145,20 @@
reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
for (int i = 0; tests[i]; i++) {
- v8::ScriptData* data =
- v8::ScriptData::PreCompile(isolate, tests[i], i::StrLength(tests[i]));
+ v8::Handle<v8::String> source = v8::String::NewFromUtf8(
+ isolate, tests[i], v8::String::kNormalString, i::StrLength(tests[i]));
+ v8::ScriptData* data = v8::ScriptData::PreCompile(source);
CHECK(data != NULL && !data->HasError());
delete data;
}
for (int i = 0; fail_tests[i]; i++) {
- v8::ScriptData* data = v8::ScriptData::PreCompile(
- isolate, fail_tests[i], i::StrLength(fail_tests[i]));
+ v8::Handle<v8::String> source =
+ v8::String::NewFromUtf8(isolate,
+ fail_tests[i],
+ v8::String::kNormalString,
+ i::StrLength(fail_tests[i]));
+ v8::ScriptData* data = v8::ScriptData::PreCompile(source);
CHECK(data == NULL || data->HasError());
delete data;
}
@@ -199,8 +205,8 @@
const char* error_source = "var x = y z;";
int error_source_length = i::StrLength(error_source);
- v8::ScriptData* preparse =
- v8::ScriptData::PreCompile(isolate, source, source_length);
+ v8::ScriptData* preparse = v8::ScriptData::PreCompile(v8::String::NewFromUtf8(
+ isolate, source, v8::String::kNormalString, source_length));
CHECK(!preparse->HasError());
bool lazy_flag = i::FLAG_lazy;
{
@@ -223,8 +229,11 @@
i::FLAG_lazy = lazy_flag;
// Syntax error.
- v8::ScriptData* error_preparse =
- v8::ScriptData::PreCompile(isolate, error_source, error_source_length);
+ v8::ScriptData* error_preparse = v8::ScriptData::PreCompile(
+ v8::String::NewFromUtf8(isolate,
+ error_source,
+ v8::String::kNormalString,
+ error_source_length));
CHECK(error_preparse->HasError());
i::ScriptDataImpl *pre_impl =
reinterpret_cast<i::ScriptDataImpl*>(error_preparse);
diff --git a/test/mjsunit/arguments-apply-deopt.js b/test/mjsunit/arguments-apply-deopt.js
new file mode 100644
index 0000000..b7251af
--- /dev/null
+++ b/test/mjsunit/arguments-apply-deopt.js
@@ -0,0 +1,77 @@
+// Copyright 2012 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.
+
+// Flags: --allow-natives-syntax
+
+(function ApplyArgumentsDeoptInReceiverMapCheck() {
+ function invoker(h, r) {
+ return function XXXXX() {
+ var res = h.apply({ fffffff : r(this) }, arguments);
+ return res;
+ };
+ }
+
+ var y = invoker(m, selfOf);
+
+ function selfOf(c) {
+ var sssss = c.self_;
+ return sssss;
+ }
+
+ function m() {
+ return this.fffffff;
+ }
+
+ y.apply({ self_ : 3 });
+ y.apply({ self_ : 3 });
+ y.apply({ self_ : 3 });
+
+ %OptimizeFunctionOnNextCall(y);
+
+ assertEquals(y.apply({ self_ : 3, uuu : 4 }), 3);
+})();
+
+(function ApplyArgumentsDeoptInReceiverExplicit() {
+ function f() { return this + 21; }
+
+ function deopt() {
+ %DeoptimizeFunction(XXXXX);
+ return 21;
+ }
+
+ function XXXXX() {
+ return f.apply(deopt(), arguments);
+ };
+
+ XXXXX();
+ XXXXX();
+ XXXXX();
+
+ %OptimizeFunctionOnNextCall(XXXXX);
+
+ assertEquals(42, XXXXX());
+})();
diff --git a/test/mjsunit/elements-kind.js b/test/mjsunit/elements-kind.js
index 857637c..b02af65 100644
--- a/test/mjsunit/elements-kind.js
+++ b/test/mjsunit/elements-kind.js
@@ -26,7 +26,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax --smi-only-arrays --expose-gc
-// Flags: --nostress-opt
+// Flags: --nostress-opt --nostress-compaction --gc-interval=-1
// Test element kind of objects.
// Since --smi-only-arrays affects builtins, its default setting at compile