Version 3.26.13 (based on bleeding_edge revision r20698)
Make maps in monomorphic IC stubs weak (issue 2073).
x64: Make sure that the upper half of a 64bit register contains 0 for int32 values (Chromium issue 360611).
Performance and stability improvements on all platforms.
git-svn-id: http://v8.googlecode.com/svn/trunk@20699 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/accessors.cc b/src/accessors.cc
index 8dbd9c9..3030e5d 100644
--- a/src/accessors.cc
+++ b/src/accessors.cc
@@ -80,10 +80,10 @@
static V8_INLINE bool CheckForName(Handle<String> name,
- String* property_name,
+ Handle<String> property_name,
int offset,
int* object_offset) {
- if (name->Equals(property_name)) {
+ if (String::Equals(name, property_name)) {
*object_offset = offset;
return true;
}
@@ -100,7 +100,7 @@
Isolate* isolate = name->GetIsolate();
if (type->Is(T::String())) {
- return CheckForName(name, isolate->heap()->length_string(),
+ return CheckForName(name, isolate->factory()->length_string(),
String::kLengthOffset, object_offset);
}
@@ -110,25 +110,25 @@
switch (map->instance_type()) {
case JS_ARRAY_TYPE:
return
- CheckForName(name, isolate->heap()->length_string(),
+ CheckForName(name, isolate->factory()->length_string(),
JSArray::kLengthOffset, object_offset);
case JS_TYPED_ARRAY_TYPE:
return
- CheckForName(name, isolate->heap()->length_string(),
+ CheckForName(name, isolate->factory()->length_string(),
JSTypedArray::kLengthOffset, object_offset) ||
- CheckForName(name, isolate->heap()->byte_length_string(),
+ CheckForName(name, isolate->factory()->byte_length_string(),
JSTypedArray::kByteLengthOffset, object_offset) ||
- CheckForName(name, isolate->heap()->byte_offset_string(),
+ CheckForName(name, isolate->factory()->byte_offset_string(),
JSTypedArray::kByteOffsetOffset, object_offset);
case JS_ARRAY_BUFFER_TYPE:
return
- CheckForName(name, isolate->heap()->byte_length_string(),
+ CheckForName(name, isolate->factory()->byte_length_string(),
JSArrayBuffer::kByteLengthOffset, object_offset);
case JS_DATA_VIEW_TYPE:
return
- CheckForName(name, isolate->heap()->byte_length_string(),
+ CheckForName(name, isolate->factory()->byte_length_string(),
JSDataView::kByteLengthOffset, object_offset) ||
- CheckForName(name, isolate->heap()->byte_offset_string(),
+ CheckForName(name, isolate->factory()->byte_offset_string(),
JSDataView::kByteOffsetOffset, object_offset);
default:
return false;
@@ -202,13 +202,12 @@
Handle<JSArray> array_handle = Handle<JSArray>::cast(object);
- bool has_exception;
- Handle<Object> uint32_v =
- Execution::ToUint32(isolate, value, &has_exception);
- if (has_exception) return Failure::Exception();
- Handle<Object> number_v =
- Execution::ToNumber(isolate, value, &has_exception);
- if (has_exception) return Failure::Exception();
+ Handle<Object> uint32_v;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, uint32_v, Execution::ToUint32(isolate, value));
+ Handle<Object> number_v;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, number_v, Execution::ToNumber(isolate, value));
if (uint32_v->Number() == number_v->Number()) {
Handle<Object> result;
diff --git a/src/api.cc b/src/api.cc
index 8d10163..d682078 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -1579,45 +1579,6 @@
}
-// --- S c r i p t D a t a ---
-
-
-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());
- return i::PreParserApi::PreParse(isolate, &stream);
- } else {
- i::GenericStringUtf16CharacterStream stream(str, 0, str->length());
- return i::PreParserApi::PreParse(isolate, &stream);
- }
-}
-
-
-ScriptData* ScriptData::New(const char* data, int length) {
- // Return an empty ScriptData if the length is obviously invalid.
- if (length % sizeof(unsigned) != 0) {
- return new i::ScriptDataImpl();
- }
-
- // Copy the data to ensure it is properly aligned.
- int deserialized_data_length = length / sizeof(unsigned);
- // If aligned, don't create a copy of the data.
- if (reinterpret_cast<intptr_t>(data) % sizeof(unsigned) == 0) {
- return new i::ScriptDataImpl(data, length);
- }
- // Copy the data to align it.
- unsigned* deserialized_data = i::NewArray<unsigned>(deserialized_data_length);
- i::CopyBytes(reinterpret_cast<char*>(deserialized_data),
- data, static_cast<size_t>(length));
-
- return new i::ScriptDataImpl(
- i::Vector<unsigned>(deserialized_data, deserialized_data_length));
-}
-
-
// --- S c r i p t s ---
@@ -1707,21 +1668,16 @@
ENTER_V8(isolate);
i::Logger::TimerEventScope timer_scope(
isolate, i::Logger::TimerEventScope::v8_execute);
- i::Object* raw_result = NULL;
- {
- i::HandleScope scope(isolate);
- i::Handle<i::JSFunction> fun =
- i::Handle<i::JSFunction>(i::JSFunction::cast(*obj), isolate);
- EXCEPTION_PREAMBLE(isolate);
- i::Handle<i::Object> receiver(
- isolate->context()->global_proxy(), isolate);
- i::Handle<i::Object> result = i::Execution::Call(
- isolate, fun, receiver, 0, NULL, &has_pending_exception);
- EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Value>());
- raw_result = *result;
- }
- i::Handle<i::Object> result(raw_result, isolate);
- return Utils::ToLocal(result);
+ i::HandleScope scope(isolate);
+ i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(obj);
+ EXCEPTION_PREAMBLE(isolate);
+ i::Handle<i::Object> receiver(
+ isolate->context()->global_proxy(), isolate);
+ i::Handle<i::Object> result;
+ has_pending_exception = !i::Execution::Call(
+ isolate, fun, receiver, 0, NULL).ToHandle(&result);
+ EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Value>());
+ return Utils::ToLocal(scope.CloseAndEscape(result));
}
@@ -1736,7 +1692,7 @@
Isolate* v8_isolate,
Source* source,
CompileOptions options) {
- i::ScriptDataImpl* script_data_impl = NULL;
+ i::ScriptData* script_data_impl = NULL;
i::CachedDataMode cached_data_mode = i::NO_CACHED_DATA;
if (options & kProduceDataToCache) {
cached_data_mode = i::PRODUCE_CACHED_DATA;
@@ -1749,11 +1705,11 @@
source->cached_data = NULL;
}
} else if (source->cached_data) {
- // FIXME(marja): Make compiler use CachedData directly. Aligning needs to be
- // taken care of.
- script_data_impl = static_cast<i::ScriptDataImpl*>(ScriptData::New(
+ // ScriptData takes care of aligning, in case the data is not aligned
+ // correctly.
+ script_data_impl = i::ScriptData::New(
reinterpret_cast<const char*>(source->cached_data->data),
- source->cached_data->length));
+ source->cached_data->length);
// We assert that the pre-data is sane, even though we can actually
// handle it if it turns out not to be in release mode.
ASSERT(script_data_impl->SanityCheck());
@@ -1842,22 +1798,15 @@
Local<Script> Script::Compile(v8::Handle<String> source,
- v8::ScriptOrigin* origin,
- ScriptData* script_data) {
+ v8::ScriptOrigin* origin) {
i::Handle<i::String> str = Utils::OpenHandle(*source);
- ScriptCompiler::CachedData* cached_data = NULL;
- if (script_data) {
- cached_data = new ScriptCompiler::CachedData(
- reinterpret_cast<const uint8_t*>(script_data->Data()),
- script_data->Length());
- }
if (origin) {
- ScriptCompiler::Source script_source(source, *origin, cached_data);
+ ScriptCompiler::Source script_source(source, *origin);
return ScriptCompiler::Compile(
reinterpret_cast<v8::Isolate*>(str->GetIsolate()),
&script_source);
}
- ScriptCompiler::Source script_source(source, cached_data);
+ ScriptCompiler::Source script_source(source);
return ScriptCompiler::Compile(
reinterpret_cast<v8::Isolate*>(str->GetIsolate()),
&script_source);
@@ -1953,8 +1902,10 @@
i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj), isolate_);
i::Handle<i::String> name = isolate_->factory()->stack_string();
if (!i::JSReceiver::HasProperty(obj, name)) return v8::Local<Value>();
- i::Handle<i::Object> value = i::Object::GetProperty(obj, name);
- if (value.is_null()) return v8::Local<Value>();
+ i::Handle<i::Object> value;
+ if (!i::Object::GetProperty(obj, name).ToHandle(&value)) {
+ return v8::Local<Value>();
+ }
return v8::Utils::ToLocal(scope.CloseAndEscape(value));
} else {
return v8::Local<Value>();
@@ -2040,33 +1991,30 @@
}
-static i::Handle<i::Object> CallV8HeapFunction(const char* name,
- i::Handle<i::Object> recv,
- int argc,
- i::Handle<i::Object> argv[],
- bool* has_pending_exception) {
+MUST_USE_RESULT static i::MaybeHandle<i::Object> CallV8HeapFunction(
+ const char* name,
+ i::Handle<i::Object> recv,
+ int argc,
+ i::Handle<i::Object> argv[]) {
i::Isolate* isolate = i::Isolate::Current();
i::Handle<i::String> fmt_str =
isolate->factory()->InternalizeUtf8String(name);
i::Handle<i::Object> object_fun =
- i::GlobalObject::GetPropertyNoExceptionThrown(
- isolate->js_builtins_object(), fmt_str);
+ i::Object::GetProperty(
+ isolate->js_builtins_object(), fmt_str).ToHandleChecked();
i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(object_fun);
- i::Handle<i::Object> value = i::Execution::Call(
- isolate, fun, recv, argc, argv, has_pending_exception);
- return value;
+ return i::Execution::Call(isolate, fun, recv, argc, argv);
}
-static i::Handle<i::Object> CallV8HeapFunction(const char* name,
- i::Handle<i::Object> data,
- bool* has_pending_exception) {
+MUST_USE_RESULT static i::MaybeHandle<i::Object> CallV8HeapFunction(
+ const char* name,
+ i::Handle<i::Object> data) {
i::Handle<i::Object> argv[] = { data };
return CallV8HeapFunction(name,
i::Isolate::Current()->js_builtins_object(),
ARRAY_SIZE(argv),
- argv,
- has_pending_exception);
+ argv);
}
@@ -2077,9 +2025,9 @@
i::HandleScope scope(isolate);
EXCEPTION_PREAMBLE(isolate);
- i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber",
- Utils::OpenHandle(this),
- &has_pending_exception);
+ i::Handle<i::Object> result;
+ has_pending_exception = !CallV8HeapFunction(
+ "GetLineNumber", Utils::OpenHandle(this)).ToHandle(&result);
EXCEPTION_BAILOUT_CHECK(isolate, 0);
return static_cast<int>(result->Number());
}
@@ -2111,10 +2059,9 @@
i::HandleScope scope(isolate);
i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
EXCEPTION_PREAMBLE(isolate);
- i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
- "GetPositionInLine",
- data_obj,
- &has_pending_exception);
+ i::Handle<i::Object> start_col_obj;
+ has_pending_exception = !CallV8HeapFunction(
+ "GetPositionInLine", data_obj).ToHandle(&start_col_obj);
EXCEPTION_BAILOUT_CHECK(isolate, 0);
return static_cast<int>(start_col_obj->Number());
}
@@ -2126,10 +2073,9 @@
i::HandleScope scope(isolate);
i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
EXCEPTION_PREAMBLE(isolate);
- i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
- "GetPositionInLine",
- data_obj,
- &has_pending_exception);
+ i::Handle<i::Object> start_col_obj;
+ has_pending_exception = !CallV8HeapFunction(
+ "GetPositionInLine", data_obj).ToHandle(&start_col_obj);
EXCEPTION_BAILOUT_CHECK(isolate, 0);
i::Handle<i::JSMessageObject> message =
i::Handle<i::JSMessageObject>::cast(data_obj);
@@ -2158,9 +2104,9 @@
ENTER_V8(isolate);
EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
EXCEPTION_PREAMBLE(isolate);
- i::Handle<i::Object> result = CallV8HeapFunction("GetSourceLine",
- Utils::OpenHandle(this),
- &has_pending_exception);
+ i::Handle<i::Object> result;
+ has_pending_exception = !CallV8HeapFunction(
+ "GetSourceLine", Utils::OpenHandle(this)).ToHandle(&result);
EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::String>());
if (result->IsString()) {
return scope.Escape(Utils::ToLocal(i::Handle<i::String>::cast(result)));
@@ -2185,7 +2131,7 @@
EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
i::Handle<i::JSArray> self = Utils::OpenHandle(this);
i::Handle<i::Object> obj =
- i::Object::GetElementNoExceptionThrown(isolate, self, index);
+ i::Object::GetElement(isolate, self, index).ToHandleChecked();
i::Handle<i::JSObject> jsobj = i::Handle<i::JSObject>::cast(obj);
return scope.Escape(Utils::StackFrameToLocal(jsobj));
}
@@ -2500,8 +2446,8 @@
const char* builtin_name) {
i::Handle<i::String> string =
isolate->factory()->InternalizeUtf8String(builtin_name);
- return *i::GlobalObject::GetPropertyNoExceptionThrown(
- isolate->js_builtins_object(), string);
+ return *i::Object::GetProperty(
+ isolate->js_builtins_object(), string).ToHandleChecked();
}
@@ -2557,7 +2503,8 @@
LOG_API(isolate, "ToString");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
- str = i::Execution::ToString(isolate, obj, &has_pending_exception);
+ has_pending_exception = !i::Execution::ToString(
+ isolate, obj).ToHandle(&str);
EXCEPTION_BAILOUT_CHECK(isolate, Local<String>());
}
return ToApiHandle<String>(str);
@@ -2574,7 +2521,8 @@
LOG_API(isolate, "ToDetailString");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
- str = i::Execution::ToDetailString(isolate, obj, &has_pending_exception);
+ has_pending_exception = !i::Execution::ToDetailString(
+ isolate, obj).ToHandle(&str);
EXCEPTION_BAILOUT_CHECK(isolate, Local<String>());
}
return ToApiHandle<String>(str);
@@ -2591,7 +2539,8 @@
LOG_API(isolate, "ToObject");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
- val = i::Execution::ToObject(isolate, obj, &has_pending_exception);
+ has_pending_exception = !i::Execution::ToObject(
+ isolate, obj).ToHandle(&val);
EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
}
return ToApiHandle<Object>(val);
@@ -2623,7 +2572,8 @@
LOG_API(isolate, "ToNumber");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
- num = i::Execution::ToNumber(isolate, obj, &has_pending_exception);
+ has_pending_exception = !i::Execution::ToNumber(
+ isolate, obj).ToHandle(&num);
EXCEPTION_BAILOUT_CHECK(isolate, Local<Number>());
}
return ToApiHandle<Number>(num);
@@ -2640,7 +2590,8 @@
LOG_API(isolate, "ToInteger");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
- num = i::Execution::ToInteger(isolate, obj, &has_pending_exception);
+ has_pending_exception = !i::Execution::ToInteger(
+ isolate, obj).ToHandle(&num);
EXCEPTION_BAILOUT_CHECK(isolate, Local<Integer>());
}
return ToApiHandle<Integer>(num);
@@ -2850,7 +2801,8 @@
LOG_API(isolate, "NumberValue");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
- num = i::Execution::ToNumber(isolate, obj, &has_pending_exception);
+ has_pending_exception = !i::Execution::ToNumber(
+ isolate, obj).ToHandle(&num);
EXCEPTION_BAILOUT_CHECK(isolate, i::OS::nan_value());
}
return num->Number();
@@ -2867,7 +2819,8 @@
LOG_API(isolate, "IntegerValue");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
- num = i::Execution::ToInteger(isolate, obj, &has_pending_exception);
+ has_pending_exception = !i::Execution::ToInteger(
+ isolate, obj).ToHandle(&num);
EXCEPTION_BAILOUT_CHECK(isolate, 0);
}
if (num->IsSmi()) {
@@ -2888,7 +2841,7 @@
LOG_API(isolate, "ToInt32");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
- num = i::Execution::ToInt32(isolate, obj, &has_pending_exception);
+ has_pending_exception = !i::Execution::ToInt32(isolate, obj).ToHandle(&num);
EXCEPTION_BAILOUT_CHECK(isolate, Local<Int32>());
}
return ToApiHandle<Int32>(num);
@@ -2905,7 +2858,8 @@
LOG_API(isolate, "ToUInt32");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
- num = i::Execution::ToUint32(isolate, obj, &has_pending_exception);
+ has_pending_exception = !i::Execution::ToUint32(
+ isolate, obj).ToHandle(&num);
EXCEPTION_BAILOUT_CHECK(isolate, Local<Uint32>());
}
return ToApiHandle<Uint32>(num);
@@ -2922,8 +2876,9 @@
LOG_API(isolate, "ToArrayIndex");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
- i::Handle<i::Object> string_obj =
- i::Execution::ToString(isolate, obj, &has_pending_exception);
+ i::Handle<i::Object> string_obj;
+ has_pending_exception = !i::Execution::ToString(
+ isolate, obj).ToHandle(&string_obj);
EXCEPTION_BAILOUT_CHECK(isolate, Local<Uint32>());
i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
uint32_t index;
@@ -2949,8 +2904,8 @@
LOG_API(isolate, "Int32Value (slow)");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
- i::Handle<i::Object> num =
- i::Execution::ToInt32(isolate, obj, &has_pending_exception);
+ i::Handle<i::Object> num;
+ has_pending_exception = !i::Execution::ToInt32(isolate, obj).ToHandle(&num);
EXCEPTION_BAILOUT_CHECK(isolate, 0);
if (num->IsSmi()) {
return i::Smi::cast(*num)->value();
@@ -2980,9 +2935,9 @@
}
i::Handle<i::Object> args[] = { other };
EXCEPTION_PREAMBLE(isolate);
- i::Handle<i::Object> result =
- CallV8HeapFunction("EQUALS", obj, ARRAY_SIZE(args), args,
- &has_pending_exception);
+ i::Handle<i::Object> result;
+ has_pending_exception = !CallV8HeapFunction(
+ "EQUALS", obj, ARRAY_SIZE(args), args).ToHandle(&result);
EXCEPTION_BAILOUT_CHECK(isolate, false);
return *result == i::Smi::FromInt(i::EQUAL);
}
@@ -3011,7 +2966,8 @@
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::Equals(i::Handle<i::String>::cast(obj),
+ i::Handle<i::String>::cast(other));
} else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
return other->IsUndefined() || other->IsUndetectableObject();
} else {
@@ -3043,8 +2999,9 @@
LOG_API(isolate, "Uint32Value");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
- i::Handle<i::Object> num =
- i::Execution::ToUint32(isolate, obj, &has_pending_exception);
+ i::Handle<i::Object> num;
+ has_pending_exception = !i::Execution::ToUint32(
+ isolate, obj).ToHandle(&num);
EXCEPTION_BAILOUT_CHECK(isolate, 0);
if (num->IsSmi()) {
return i::Smi::cast(*num)->value();
@@ -3188,7 +3145,8 @@
i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
if (!key_obj->IsName()) {
EXCEPTION_PREAMBLE(isolate);
- key_obj = i::Execution::ToString(isolate, key_obj, &has_pending_exception);
+ has_pending_exception = !i::Execution::ToString(
+ isolate, key_obj).ToHandle(&key_obj);
EXCEPTION_BAILOUT_CHECK(isolate, static_cast<PropertyAttribute>(NONE));
}
i::Handle<i::Name> key_name = i::Handle<i::Name>::cast(key_obj);
@@ -3918,15 +3876,17 @@
fun = i::Handle<i::JSFunction>::cast(obj);
} else {
EXCEPTION_PREAMBLE(isolate);
- i::Handle<i::Object> delegate = i::Execution::TryGetFunctionDelegate(
- isolate, obj, &has_pending_exception);
+ i::Handle<i::Object> delegate;
+ has_pending_exception = !i::Execution::TryGetFunctionDelegate(
+ isolate, obj).ToHandle(&delegate);
EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
fun = i::Handle<i::JSFunction>::cast(delegate);
recv_obj = obj;
}
EXCEPTION_PREAMBLE(isolate);
- i::Handle<i::Object> returned = i::Execution::Call(
- isolate, fun, recv_obj, argc, args, &has_pending_exception, true);
+ i::Handle<i::Object> returned;
+ has_pending_exception = !i::Execution::Call(
+ isolate, fun, recv_obj, argc, args, true).ToHandle(&returned);
EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Value>());
return Utils::ToLocal(scope.CloseAndEscape(returned));
}
@@ -3948,21 +3908,24 @@
if (obj->IsJSFunction()) {
i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(obj);
EXCEPTION_PREAMBLE(isolate);
- i::Handle<i::Object> returned =
- i::Execution::New(fun, argc, args, &has_pending_exception);
+ i::Handle<i::Object> returned;
+ has_pending_exception = !i::Execution::New(
+ fun, argc, args).ToHandle(&returned);
EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>());
return Utils::ToLocal(scope.CloseAndEscape(
i::Handle<i::JSObject>::cast(returned)));
}
EXCEPTION_PREAMBLE(isolate);
- i::Handle<i::Object> delegate = i::Execution::TryGetConstructorDelegate(
- isolate, obj, &has_pending_exception);
+ i::Handle<i::Object> delegate;
+ has_pending_exception = !i::Execution::TryGetConstructorDelegate(
+ isolate, obj).ToHandle(&delegate);
EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
if (!delegate->IsUndefined()) {
i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(delegate);
EXCEPTION_PREAMBLE(isolate);
- i::Handle<i::Object> returned = i::Execution::Call(
- isolate, fun, obj, argc, args, &has_pending_exception);
+ i::Handle<i::Object> returned;
+ has_pending_exception = !i::Execution::Call(
+ isolate, fun, obj, argc, args).ToHandle(&returned);
EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>());
ASSERT(!delegate->IsUndefined());
return Utils::ToLocal(scope.CloseAndEscape(returned));
@@ -4003,8 +3966,9 @@
STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
EXCEPTION_PREAMBLE(isolate);
- i::Handle<i::Object> returned =
- i::Execution::New(function, argc, args, &has_pending_exception);
+ i::Handle<i::Object> returned;
+ has_pending_exception = !i::Execution::New(
+ function, argc, args).ToHandle(&returned);
EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>());
return scope.Escape(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
}
@@ -4018,21 +3982,17 @@
ENTER_V8(isolate);
i::Logger::TimerEventScope timer_scope(
isolate, i::Logger::TimerEventScope::v8_execute);
- i::Object* raw_result = NULL;
- {
- i::HandleScope scope(isolate);
- i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
- i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
- STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
- i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
- EXCEPTION_PREAMBLE(isolate);
- i::Handle<i::Object> returned = i::Execution::Call(
- isolate, fun, recv_obj, argc, args, &has_pending_exception, true);
- EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Object>());
- raw_result = *returned;
- }
- i::Handle<i::Object> result(raw_result, isolate);
- return Utils::ToLocal(result);
+ i::HandleScope scope(isolate);
+ i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
+ i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
+ STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
+ i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
+ EXCEPTION_PREAMBLE(isolate);
+ i::Handle<i::Object> returned;
+ has_pending_exception = !i::Execution::Call(
+ isolate, fun, recv_obj, argc, args, true).ToHandle(&returned);
+ EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Object>());
+ return Utils::ToLocal(scope.CloseAndEscape(returned));
}
@@ -5305,9 +5265,9 @@
LOG_API(isolate, "ObjectTemplate::NewInstance");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
- i::Handle<i::Object> obj =
- i::Execution::InstantiateObject(Utils::OpenHandle(this),
- &has_pending_exception);
+ i::Handle<i::Object> obj;
+ has_pending_exception = !i::Execution::InstantiateObject(
+ Utils::OpenHandle(this)).ToHandle(&obj);
EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
}
@@ -5320,9 +5280,9 @@
LOG_API(isolate, "FunctionTemplate::GetFunction");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
- i::Handle<i::Object> obj =
- i::Execution::InstantiateFunction(Utils::OpenHandle(this),
- &has_pending_exception);
+ i::Handle<i::Object> obj;
+ has_pending_exception = !i::Execution::InstantiateFunction(
+ Utils::OpenHandle(this)).ToHandle(&obj);
EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Function>());
return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
}
@@ -5704,8 +5664,9 @@
}
ENTER_V8(i_isolate);
EXCEPTION_PREAMBLE(i_isolate);
- i::Handle<i::Object> obj =
- i::Execution::NewDate(i_isolate, time, &has_pending_exception);
+ i::Handle<i::Object> obj;
+ has_pending_exception = !i::Execution::NewDate(
+ i_isolate, time).ToHandle(&obj);
EXCEPTION_BAILOUT_CHECK(i_isolate, Local<v8::Value>());
return Utils::ToLocal(obj);
}
@@ -5765,10 +5726,10 @@
LOG_API(isolate, "RegExp::New");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
- i::Handle<i::JSRegExp> obj = i::Execution::NewJSRegExp(
+ i::Handle<i::JSRegExp> obj;
+ has_pending_exception = !i::Execution::NewJSRegExp(
Utils::OpenHandle(*pattern),
- RegExpFlagsToString(flags),
- &has_pending_exception);
+ RegExpFlagsToString(flags)).ToHandle(&obj);
EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::RegExp>());
return Utils::ToLocal(i::Handle<i::JSRegExp>::cast(obj));
}
@@ -5852,14 +5813,14 @@
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
i::Handle<i::Object> argv[] = { obj };
- i::Handle<i::Object> b = i::Execution::Call(
+ i::Handle<i::Object> b;
+ has_pending_exception = !i::Execution::Call(
isolate,
handle(
isolate->context()->global_object()->native_context()->is_promise()),
isolate->factory()->undefined_value(),
ARRAY_SIZE(argv), argv,
- &has_pending_exception,
- false);
+ false).ToHandle(&b);
EXCEPTION_BAILOUT_CHECK(isolate, false);
return b->BooleanValue();
}
@@ -5870,14 +5831,14 @@
LOG_API(isolate, "Promise::Resolver::New");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
- i::Handle<i::Object> result = i::Execution::Call(
+ i::Handle<i::Object> result;
+ has_pending_exception = !i::Execution::Call(
isolate,
handle(isolate->context()->global_object()->native_context()->
promise_create()),
isolate->factory()->undefined_value(),
0, NULL,
- &has_pending_exception,
- false);
+ false).ToHandle(&result);
EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise::Resolver>());
return Local<Promise::Resolver>::Cast(Utils::ToLocal(result));
}
@@ -5896,14 +5857,13 @@
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
i::Handle<i::Object> argv[] = { promise, Utils::OpenHandle(*value) };
- i::Execution::Call(
+ has_pending_exception = i::Execution::Call(
isolate,
handle(isolate->context()->global_object()->native_context()->
promise_resolve()),
isolate->factory()->undefined_value(),
ARRAY_SIZE(argv), argv,
- &has_pending_exception,
- false);
+ false).is_null();
EXCEPTION_BAILOUT_CHECK(isolate, /* void */ ;);
}
@@ -5915,14 +5875,13 @@
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
i::Handle<i::Object> argv[] = { promise, Utils::OpenHandle(*value) };
- i::Execution::Call(
+ has_pending_exception = i::Execution::Call(
isolate,
handle(isolate->context()->global_object()->native_context()->
promise_reject()),
isolate->factory()->undefined_value(),
ARRAY_SIZE(argv), argv,
- &has_pending_exception,
- false);
+ false).is_null();
EXCEPTION_BAILOUT_CHECK(isolate, /* void */ ;);
}
@@ -5934,14 +5893,14 @@
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
i::Handle<i::Object> argv[] = { Utils::OpenHandle(*handler) };
- i::Handle<i::Object> result = i::Execution::Call(
+ i::Handle<i::Object> result;
+ has_pending_exception = !i::Execution::Call(
isolate,
handle(isolate->context()->global_object()->native_context()->
promise_chain()),
promise,
ARRAY_SIZE(argv), argv,
- &has_pending_exception,
- false);
+ false).ToHandle(&result);
EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise>());
return Local<Promise>::Cast(Utils::ToLocal(result));
}
@@ -5954,14 +5913,14 @@
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
i::Handle<i::Object> argv[] = { Utils::OpenHandle(*handler) };
- i::Handle<i::Object> result = i::Execution::Call(
+ i::Handle<i::Object> result;
+ has_pending_exception = !i::Execution::Call(
isolate,
handle(isolate->context()->global_object()->native_context()->
promise_catch()),
promise,
ARRAY_SIZE(argv), argv,
- &has_pending_exception,
- false);
+ false).ToHandle(&result);
EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise>());
return Local<Promise>::Cast(Utils::ToLocal(result));
}
@@ -6970,17 +6929,17 @@
if (!isolate->IsInitialized()) return Local<Value>();
ON_BAILOUT(isolate, "v8::Debug::Call()", return Local<Value>());
ENTER_V8(isolate);
- i::Handle<i::Object> result;
+ i::MaybeHandle<i::Object> maybe_result;
EXCEPTION_PREAMBLE(isolate);
if (data.IsEmpty()) {
- result = isolate->debugger()->Call(Utils::OpenHandle(*fun),
- isolate->factory()->undefined_value(),
- &has_pending_exception);
+ maybe_result = isolate->debugger()->Call(
+ Utils::OpenHandle(*fun), isolate->factory()->undefined_value());
} else {
- result = isolate->debugger()->Call(Utils::OpenHandle(*fun),
- Utils::OpenHandle(*data),
- &has_pending_exception);
+ maybe_result = isolate->debugger()->Call(
+ Utils::OpenHandle(*fun), Utils::OpenHandle(*data));
}
+ i::Handle<i::Object> result;
+ has_pending_exception = !maybe_result.ToHandle(&result);
EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
return Utils::ToLocal(result);
}
@@ -7001,8 +6960,8 @@
isolate_debug->debug_context()->global_object());
i::Handle<i::String> name = isolate->factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR("MakeMirror"));
- i::Handle<i::Object> fun_obj = i::Object::GetProperty(debug, name);
- ASSERT(!fun_obj.is_null());
+ i::Handle<i::Object> fun_obj =
+ i::Object::GetProperty(debug, name).ToHandleChecked();
i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun);
const int kArgc = 1;
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index ba5053f..4d6ffb9 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -4525,13 +4525,14 @@
}
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
- if (check->Equals(isolate()->heap()->number_string())) {
+ Factory* factory = isolate()->factory();
+ if (String::Equals(check, factory->number_string())) {
__ JumpIfSmi(r0, if_true);
__ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
__ cmp(r0, ip);
Split(eq, if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->string_string())) {
+ } else if (String::Equals(check, factory->string_string())) {
__ JumpIfSmi(r0, if_false);
// Check for undetectable objects => false.
__ CompareObjectType(r0, r0, r1, FIRST_NONSTRING_TYPE);
@@ -4539,20 +4540,20 @@
__ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
__ tst(r1, Operand(1 << Map::kIsUndetectable));
Split(eq, if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->symbol_string())) {
+ } else if (String::Equals(check, factory->symbol_string())) {
__ JumpIfSmi(r0, if_false);
__ CompareObjectType(r0, r0, r1, SYMBOL_TYPE);
Split(eq, if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->boolean_string())) {
+ } else if (String::Equals(check, factory->boolean_string())) {
__ CompareRoot(r0, Heap::kTrueValueRootIndex);
__ b(eq, if_true);
__ CompareRoot(r0, Heap::kFalseValueRootIndex);
Split(eq, if_true, if_false, fall_through);
} else if (FLAG_harmony_typeof &&
- check->Equals(isolate()->heap()->null_string())) {
+ String::Equals(check, factory->null_string())) {
__ CompareRoot(r0, Heap::kNullValueRootIndex);
Split(eq, if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->undefined_string())) {
+ } else if (String::Equals(check, factory->undefined_string())) {
__ CompareRoot(r0, Heap::kUndefinedValueRootIndex);
__ b(eq, if_true);
__ JumpIfSmi(r0, if_false);
@@ -4562,14 +4563,14 @@
__ tst(r1, Operand(1 << Map::kIsUndetectable));
Split(ne, if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->function_string())) {
+ } else if (String::Equals(check, factory->function_string())) {
__ JumpIfSmi(r0, if_false);
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
__ CompareObjectType(r0, r0, r1, JS_FUNCTION_TYPE);
__ b(eq, if_true);
__ cmp(r1, Operand(JS_FUNCTION_PROXY_TYPE));
Split(eq, if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->object_string())) {
+ } else if (String::Equals(check, factory->object_string())) {
__ JumpIfSmi(r0, if_false);
if (!FLAG_harmony_typeof) {
__ CompareRoot(r0, Heap::kNullValueRootIndex);
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index b20c0e5..34d98b7 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -5496,13 +5496,14 @@
Handle<String> type_name) {
Condition final_branch_condition = kNoCondition;
Register scratch = scratch0();
- if (type_name->Equals(heap()->number_string())) {
+ Factory* factory = isolate()->factory();
+ if (String::Equals(type_name, factory->number_string())) {
__ JumpIfSmi(input, true_label);
__ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
__ CompareRoot(scratch, Heap::kHeapNumberMapRootIndex);
final_branch_condition = eq;
- } else if (type_name->Equals(heap()->string_string())) {
+ } else if (String::Equals(type_name, factory->string_string())) {
__ JumpIfSmi(input, false_label);
__ CompareObjectType(input, scratch, no_reg, FIRST_NONSTRING_TYPE);
__ b(ge, false_label);
@@ -5510,22 +5511,23 @@
__ tst(scratch, Operand(1 << Map::kIsUndetectable));
final_branch_condition = eq;
- } else if (type_name->Equals(heap()->symbol_string())) {
+ } else if (String::Equals(type_name, factory->symbol_string())) {
__ JumpIfSmi(input, false_label);
__ CompareObjectType(input, scratch, no_reg, SYMBOL_TYPE);
final_branch_condition = eq;
- } else if (type_name->Equals(heap()->boolean_string())) {
+ } else if (String::Equals(type_name, factory->boolean_string())) {
__ CompareRoot(input, Heap::kTrueValueRootIndex);
__ b(eq, true_label);
__ CompareRoot(input, Heap::kFalseValueRootIndex);
final_branch_condition = eq;
- } else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_string())) {
+ } else if (FLAG_harmony_typeof &&
+ String::Equals(type_name, factory->null_string())) {
__ CompareRoot(input, Heap::kNullValueRootIndex);
final_branch_condition = eq;
- } else if (type_name->Equals(heap()->undefined_string())) {
+ } else if (String::Equals(type_name, factory->undefined_string())) {
__ CompareRoot(input, Heap::kUndefinedValueRootIndex);
__ b(eq, true_label);
__ JumpIfSmi(input, false_label);
@@ -5535,7 +5537,7 @@
__ tst(scratch, Operand(1 << Map::kIsUndetectable));
final_branch_condition = ne;
- } else if (type_name->Equals(heap()->function_string())) {
+ } else if (String::Equals(type_name, factory->function_string())) {
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
Register type_reg = scratch;
__ JumpIfSmi(input, false_label);
@@ -5544,7 +5546,7 @@
__ cmp(type_reg, Operand(JS_FUNCTION_PROXY_TYPE));
final_branch_condition = eq;
- } else if (type_name->Equals(heap()->object_string())) {
+ } else if (String::Equals(type_name, factory->object_string())) {
Register map = scratch;
__ JumpIfSmi(input, false_label);
if (!FLAG_harmony_typeof) {
diff --git a/src/arm64/full-codegen-arm64.cc b/src/arm64/full-codegen-arm64.cc
index 819868b..5679ccd 100644
--- a/src/arm64/full-codegen-arm64.cc
+++ b/src/arm64/full-codegen-arm64.cc
@@ -4238,13 +4238,14 @@
}
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
- if (check->Equals(isolate()->heap()->number_string())) {
+ Factory* factory = isolate()->factory();
+ if (String::Equals(check, factory->number_string())) {
ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof number_string");
__ JumpIfSmi(x0, if_true);
__ Ldr(x0, FieldMemOperand(x0, HeapObject::kMapOffset));
__ CompareRoot(x0, Heap::kHeapNumberMapRootIndex);
Split(eq, if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->string_string())) {
+ } else if (String::Equals(check, factory->string_string())) {
ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof string_string");
__ JumpIfSmi(x0, if_false);
// Check for undetectable objects => false.
@@ -4252,22 +4253,22 @@
__ Ldrb(x1, FieldMemOperand(x0, Map::kBitFieldOffset));
__ TestAndSplit(x1, 1 << Map::kIsUndetectable, if_true, if_false,
fall_through);
- } else if (check->Equals(isolate()->heap()->symbol_string())) {
+ } else if (String::Equals(check, factory->symbol_string())) {
ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof symbol_string");
__ JumpIfSmi(x0, if_false);
__ CompareObjectType(x0, x0, x1, SYMBOL_TYPE);
Split(eq, if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->boolean_string())) {
+ } else if (String::Equals(check, factory->boolean_string())) {
ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof boolean_string");
__ JumpIfRoot(x0, Heap::kTrueValueRootIndex, if_true);
__ CompareRoot(x0, Heap::kFalseValueRootIndex);
Split(eq, if_true, if_false, fall_through);
} else if (FLAG_harmony_typeof &&
- check->Equals(isolate()->heap()->null_string())) {
+ String::Equals(check, factory->null_string())) {
ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof null_string");
__ CompareRoot(x0, Heap::kNullValueRootIndex);
Split(eq, if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->undefined_string())) {
+ } else if (String::Equals(check, factory->undefined_string())) {
ASM_LOCATION(
"FullCodeGenerator::EmitLiteralCompareTypeof undefined_string");
__ JumpIfRoot(x0, Heap::kUndefinedValueRootIndex, if_true);
@@ -4277,7 +4278,7 @@
__ Ldrb(x1, FieldMemOperand(x0, Map::kBitFieldOffset));
__ TestAndSplit(x1, 1 << Map::kIsUndetectable, if_false, if_true,
fall_through);
- } else if (check->Equals(isolate()->heap()->function_string())) {
+ } else if (String::Equals(check, factory->function_string())) {
ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof function_string");
__ JumpIfSmi(x0, if_false);
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
@@ -4285,7 +4286,7 @@
__ CompareAndSplit(x11, JS_FUNCTION_PROXY_TYPE, eq, if_true, if_false,
fall_through);
- } else if (check->Equals(isolate()->heap()->object_string())) {
+ } else if (String::Equals(check, factory->object_string())) {
ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof object_string");
__ JumpIfSmi(x0, if_false);
if (!FLAG_harmony_typeof) {
diff --git a/src/arm64/lithium-codegen-arm64.cc b/src/arm64/lithium-codegen-arm64.cc
index d885edd..99f3b27 100644
--- a/src/arm64/lithium-codegen-arm64.cc
+++ b/src/arm64/lithium-codegen-arm64.cc
@@ -5715,7 +5715,8 @@
Label* false_label = instr->FalseLabel(chunk_);
Register value = ToRegister(instr->value());
- if (type_name->Equals(heap()->number_string())) {
+ Factory* factory = isolate()->factory();
+ if (String::Equals(type_name, factory->number_string())) {
ASSERT(instr->temp1() != NULL);
Register map = ToRegister(instr->temp1());
@@ -5724,7 +5725,7 @@
__ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
EmitBranch(instr, eq);
- } else if (type_name->Equals(heap()->string_string())) {
+ } else if (String::Equals(type_name, factory->string_string())) {
ASSERT((instr->temp1() != NULL) && (instr->temp2() != NULL));
Register map = ToRegister(instr->temp1());
Register scratch = ToRegister(instr->temp2());
@@ -5735,7 +5736,7 @@
__ Ldrb(scratch, FieldMemOperand(map, Map::kBitFieldOffset));
EmitTestAndBranch(instr, eq, scratch, 1 << Map::kIsUndetectable);
- } else if (type_name->Equals(heap()->symbol_string())) {
+ } else if (String::Equals(type_name, factory->symbol_string())) {
ASSERT((instr->temp1() != NULL) && (instr->temp2() != NULL));
Register map = ToRegister(instr->temp1());
Register scratch = ToRegister(instr->temp2());
@@ -5744,16 +5745,17 @@
__ CompareObjectType(value, map, scratch, SYMBOL_TYPE);
EmitBranch(instr, eq);
- } else if (type_name->Equals(heap()->boolean_string())) {
+ } else if (String::Equals(type_name, factory->boolean_string())) {
__ JumpIfRoot(value, Heap::kTrueValueRootIndex, true_label);
__ CompareRoot(value, Heap::kFalseValueRootIndex);
EmitBranch(instr, eq);
- } else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_string())) {
+ } else if (FLAG_harmony_typeof &&
+ String::Equals(type_name, factory->null_string())) {
__ CompareRoot(value, Heap::kNullValueRootIndex);
EmitBranch(instr, eq);
- } else if (type_name->Equals(heap()->undefined_string())) {
+ } else if (String::Equals(type_name, factory->undefined_string())) {
ASSERT(instr->temp1() != NULL);
Register scratch = ToRegister(instr->temp1());
@@ -5764,7 +5766,7 @@
__ Ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
EmitTestAndBranch(instr, ne, scratch, 1 << Map::kIsUndetectable);
- } else if (type_name->Equals(heap()->function_string())) {
+ } else if (String::Equals(type_name, factory->function_string())) {
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
ASSERT(instr->temp1() != NULL);
Register type = ToRegister(instr->temp1());
@@ -5774,7 +5776,7 @@
// HeapObject's type has been loaded into type register by JumpIfObjectType.
EmitCompareAndBranch(instr, eq, type, JS_FUNCTION_PROXY_TYPE);
- } else if (type_name->Equals(heap()->object_string())) {
+ } else if (String::Equals(type_name, factory->object_string())) {
ASSERT((instr->temp1() != NULL) && (instr->temp2() != NULL));
Register map = ToRegister(instr->temp1());
Register scratch = ToRegister(instr->temp2());
diff --git a/src/ast.cc b/src/ast.cc
index b522c98..b9e0b38 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -78,7 +78,8 @@
// The global identifier "undefined" is immutable. Everything
// else could be reassigned.
return var != NULL && var->location() == Variable::UNALLOCATED &&
- var_proxy->name()->Equals(isolate->heap()->undefined_string());
+ String::Equals(var_proxy->name(),
+ isolate->factory()->undefined_string());
}
@@ -207,9 +208,10 @@
emit_store_ = true;
key_ = key;
value_ = value;
- Object* k = *key->value();
+ Handle<Object> k = key->value();
if (k->IsInternalizedString() &&
- zone->isolate()->heap()->proto_string()->Equals(String::cast(k))) {
+ String::Equals(Handle<String>::cast(k),
+ zone->isolate()->factory()->proto_string())) {
kind_ = PROTOTYPE;
} else if (value_->AsMaterializedLiteral() != NULL) {
kind_ = MATERIALIZED_LITERAL;
diff --git a/src/ast.h b/src/ast.h
index 486db60..ed3a8b6 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -1394,7 +1394,7 @@
static bool Match(void* literal1, void* literal2) {
Handle<String> s1 = static_cast<Literal*>(literal1)->ToString();
Handle<String> s2 = static_cast<Literal*>(literal2)->ToString();
- return s1->Equals(*s2);
+ return String::Equals(s1, s2);
}
TypeFeedbackId LiteralFeedbackId() const { return reuse(id()); }
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 4cfebad..ba08aad 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -383,8 +383,7 @@
void Genesis::SetFunctionInstanceDescriptor(
Handle<Map> map, PrototypePropertyMode prototypeMode) {
int size = (prototypeMode == DONT_ADD_PROTOTYPE) ? 4 : 5;
- Handle<DescriptorArray> descriptors(factory()->NewDescriptorArray(0, size));
- DescriptorArray::WhitenessWitness witness(*descriptors);
+ Map::EnsureDescriptorSlack(map, size);
Handle<Foreign> length(factory()->NewForeign(&Accessors::FunctionLength));
Handle<Foreign> name(factory()->NewForeign(&Accessors::FunctionName));
@@ -396,23 +395,22 @@
}
PropertyAttributes attribs = static_cast<PropertyAttributes>(
DONT_ENUM | DONT_DELETE | READ_ONLY);
- map->set_instance_descriptors(*descriptors);
{ // Add length.
CallbacksDescriptor d(factory()->length_string(), length, attribs);
- map->AppendDescriptor(&d, witness);
+ map->AppendDescriptor(&d);
}
{ // Add name.
CallbacksDescriptor d(factory()->name_string(), name, attribs);
- map->AppendDescriptor(&d, witness);
+ map->AppendDescriptor(&d);
}
{ // Add arguments.
CallbacksDescriptor d(factory()->arguments_string(), args, attribs);
- map->AppendDescriptor(&d, witness);
+ map->AppendDescriptor(&d);
}
{ // Add caller.
CallbacksDescriptor d(factory()->caller_string(), caller, attribs);
- map->AppendDescriptor(&d, witness);
+ map->AppendDescriptor(&d);
}
if (prototypeMode != DONT_ADD_PROTOTYPE) {
// Add prototype.
@@ -420,7 +418,7 @@
attribs = static_cast<PropertyAttributes>(attribs & ~READ_ONLY);
}
CallbacksDescriptor d(factory()->prototype_string(), prototype, attribs);
- map->AppendDescriptor(&d, witness);
+ map->AppendDescriptor(&d);
}
}
@@ -522,8 +520,7 @@
void Genesis::SetStrictFunctionInstanceDescriptor(
Handle<Map> map, PrototypePropertyMode prototypeMode) {
int size = (prototypeMode == DONT_ADD_PROTOTYPE) ? 4 : 5;
- Handle<DescriptorArray> descriptors(factory()->NewDescriptorArray(0, size));
- DescriptorArray::WhitenessWitness witness(*descriptors);
+ Map::EnsureDescriptorSlack(map, size);
Handle<Foreign> length(factory()->NewForeign(&Accessors::FunctionLength));
Handle<Foreign> name(factory()->NewForeign(&Accessors::FunctionName));
@@ -537,31 +534,30 @@
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
PropertyAttributes ro_attribs =
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
- map->set_instance_descriptors(*descriptors);
{ // Add length.
CallbacksDescriptor d(factory()->length_string(), length, ro_attribs);
- map->AppendDescriptor(&d, witness);
+ map->AppendDescriptor(&d);
}
{ // Add name.
CallbacksDescriptor d(factory()->name_string(), name, ro_attribs);
- map->AppendDescriptor(&d, witness);
+ map->AppendDescriptor(&d);
}
{ // Add arguments.
CallbacksDescriptor d(factory()->arguments_string(), arguments,
rw_attribs);
- map->AppendDescriptor(&d, witness);
+ map->AppendDescriptor(&d);
}
{ // Add caller.
CallbacksDescriptor d(factory()->caller_string(), caller, rw_attribs);
- map->AppendDescriptor(&d, witness);
+ map->AppendDescriptor(&d);
}
if (prototypeMode != DONT_ADD_PROTOTYPE) {
// Add prototype.
PropertyAttributes attribs =
prototypeMode == ADD_WRITEABLE_PROTOTYPE ? rw_attribs : ro_attribs;
CallbacksDescriptor d(factory()->prototype_string(), prototype, attribs);
- map->AppendDescriptor(&d, witness);
+ map->AppendDescriptor(&d);
}
}
@@ -861,19 +857,15 @@
// This assert protects an optimization in
// HGraphBuilder::JSArrayBuilder::EmitMapCode()
ASSERT(initial_map->elements_kind() == GetInitialFastElementsKind());
-
- Handle<DescriptorArray> array_descriptors(
- factory->NewDescriptorArray(0, 1));
- DescriptorArray::WhitenessWitness witness(*array_descriptors);
+ Map::EnsureDescriptorSlack(initial_map, 1);
Handle<Foreign> array_length(factory->NewForeign(&Accessors::ArrayLength));
PropertyAttributes attribs = static_cast<PropertyAttributes>(
DONT_ENUM | DONT_DELETE);
- initial_map->set_instance_descriptors(*array_descriptors);
{ // Add length.
CallbacksDescriptor d(factory->length_string(), array_length, attribs);
- array_function->initial_map()->AppendDescriptor(&d, witness);
+ array_function->initial_map()->AppendDescriptor(&d);
}
// array_function is used internally. JS code creating array object should
@@ -916,19 +908,16 @@
Handle<Map> string_map =
Handle<Map>(native_context()->string_function()->initial_map());
- Handle<DescriptorArray> string_descriptors(
- factory->NewDescriptorArray(0, 1));
- DescriptorArray::WhitenessWitness witness(*string_descriptors);
+ Map::EnsureDescriptorSlack(string_map, 1);
Handle<Foreign> string_length(
factory->NewForeign(&Accessors::StringLength));
PropertyAttributes attribs = static_cast<PropertyAttributes>(
DONT_ENUM | DONT_DELETE | READ_ONLY);
- string_map->set_instance_descriptors(*string_descriptors);
{ // Add length.
CallbacksDescriptor d(factory->length_string(), string_length, attribs);
- string_map->AppendDescriptor(&d, witness);
+ string_map->AppendDescriptor(&d);
}
}
@@ -958,9 +947,7 @@
PropertyAttributes final =
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
- Handle<DescriptorArray> descriptors = factory->NewDescriptorArray(0, 5);
- DescriptorArray::WhitenessWitness witness(*descriptors);
- initial_map->set_instance_descriptors(*descriptors);
+ Map::EnsureDescriptorSlack(initial_map, 5);
{
// ECMA-262, section 15.10.7.1.
@@ -968,7 +955,7 @@
JSRegExp::kSourceFieldIndex,
final,
Representation::Tagged());
- initial_map->AppendDescriptor(&field, witness);
+ initial_map->AppendDescriptor(&field);
}
{
// ECMA-262, section 15.10.7.2.
@@ -976,7 +963,7 @@
JSRegExp::kGlobalFieldIndex,
final,
Representation::Tagged());
- initial_map->AppendDescriptor(&field, witness);
+ initial_map->AppendDescriptor(&field);
}
{
// ECMA-262, section 15.10.7.3.
@@ -984,7 +971,7 @@
JSRegExp::kIgnoreCaseFieldIndex,
final,
Representation::Tagged());
- initial_map->AppendDescriptor(&field, witness);
+ initial_map->AppendDescriptor(&field);
}
{
// ECMA-262, section 15.10.7.4.
@@ -992,7 +979,7 @@
JSRegExp::kMultilineFieldIndex,
final,
Representation::Tagged());
- initial_map->AppendDescriptor(&field, witness);
+ initial_map->AppendDescriptor(&field);
}
{
// ECMA-262, section 15.10.7.5.
@@ -1002,7 +989,7 @@
JSRegExp::kLastIndexFieldIndex,
writable,
Representation::Tagged());
- initial_map->AppendDescriptor(&field, witness);
+ initial_map->AppendDescriptor(&field);
}
initial_map->set_inobject_properties(5);
@@ -1175,26 +1162,24 @@
Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE,
Heap::kStrictArgumentsObjectSize);
// Create the descriptor array for the arguments object.
- Handle<DescriptorArray> descriptors = factory->NewDescriptorArray(0, 3);
- DescriptorArray::WhitenessWitness witness(*descriptors);
- map->set_instance_descriptors(*descriptors);
+ Map::EnsureDescriptorSlack(map, 3);
{ // length
FieldDescriptor d(
factory->length_string(), 0, DONT_ENUM, Representation::Tagged());
- map->AppendDescriptor(&d, witness);
+ map->AppendDescriptor(&d);
}
{ // callee
CallbacksDescriptor d(factory->callee_string(),
callee,
attributes);
- map->AppendDescriptor(&d, witness);
+ map->AppendDescriptor(&d);
}
{ // caller
CallbacksDescriptor d(factory->caller_string(),
caller,
attributes);
- map->AppendDescriptor(&d, witness);
+ map->AppendDescriptor(&d);
}
map->set_function_with_prototype(true);
@@ -1380,11 +1365,8 @@
object_function, JSGeneratorObject::kResultPropertyCount);
ASSERT(generator_result_map->inobject_properties() ==
JSGeneratorObject::kResultPropertyCount);
-
- Handle<DescriptorArray> descriptors = factory()->NewDescriptorArray(0,
- JSGeneratorObject::kResultPropertyCount);
- DescriptorArray::WhitenessWitness witness(*descriptors);
- generator_result_map->set_instance_descriptors(*descriptors);
+ Map::EnsureDescriptorSlack(
+ generator_result_map, JSGeneratorObject::kResultPropertyCount);
Handle<String> value_string = factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR("value"));
@@ -1392,7 +1374,7 @@
JSGeneratorObject::kResultValuePropertyIndex,
NONE,
Representation::Tagged());
- generator_result_map->AppendDescriptor(&value_descr, witness);
+ generator_result_map->AppendDescriptor(&value_descr);
Handle<String> done_string = factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR("done"));
@@ -1400,7 +1382,7 @@
JSGeneratorObject::kResultDonePropertyIndex,
NONE,
Representation::Tagged());
- generator_result_map->AppendDescriptor(&done_descr, witness);
+ generator_result_map->AppendDescriptor(&done_descr);
generator_result_map->set_unused_property_fields(0);
ASSERT_EQ(JSGeneratorObject::kResultSize,
@@ -1508,18 +1490,16 @@
? top_context->builtins()
: top_context->global_object(),
isolate);
- bool has_pending_exception;
- Execution::Call(isolate, fun, receiver, 0, NULL, &has_pending_exception);
- if (has_pending_exception) return false;
- return true;
+ return !Execution::Call(
+ isolate, fun, receiver, 0, NULL).is_null();
}
#define INSTALL_NATIVE(Type, name, var) \
Handle<String> var##_name = \
- factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR(name)); \
- Handle<Object> var##_native = GlobalObject::GetPropertyNoExceptionThrown( \
- handle(native_context()->builtins()), var##_name); \
+ factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR(name)); \
+ Handle<Object> var##_native = Object::GetProperty( \
+ handle(native_context()->builtins()), var##_name).ToHandleChecked(); \
native_context()->set_##var(Type::cast(*var##_native));
@@ -1608,20 +1588,17 @@
array_function->set_initial_map(*initial_map);
// Make "length" magic on instances.
- Handle<DescriptorArray> array_descriptors(
- factory()->NewDescriptorArray(0, 1));
- DescriptorArray::WhitenessWitness witness(*array_descriptors);
+ Map::EnsureDescriptorSlack(initial_map, 1);
Handle<Foreign> array_length(factory()->NewForeign(
&Accessors::ArrayLength));
PropertyAttributes attribs = static_cast<PropertyAttributes>(
DONT_ENUM | DONT_DELETE);
- initial_map->set_instance_descriptors(*array_descriptors);
{ // Add length.
CallbacksDescriptor d(
factory()->length_string(), array_length, attribs);
- array_function->initial_map()->AppendDescriptor(&d, witness);
+ array_function->initial_map()->AppendDescriptor(&d);
}
return array_function;
@@ -1702,10 +1679,7 @@
native_context()->set_script_function(*script_fun);
Handle<Map> script_map = Handle<Map>(script_fun->initial_map());
-
- Handle<DescriptorArray> script_descriptors(
- factory()->NewDescriptorArray(0, 13));
- DescriptorArray::WhitenessWitness witness(*script_descriptors);
+ Map::EnsureDescriptorSlack(script_map, 13);
Handle<Foreign> script_source(
factory()->NewForeign(&Accessors::ScriptSource));
@@ -1757,61 +1731,60 @@
factory()->NewForeign(&Accessors::ScriptEvalFromFunctionName));
PropertyAttributes attribs =
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
- script_map->set_instance_descriptors(*script_descriptors);
{
CallbacksDescriptor d(
factory()->source_string(), script_source, attribs);
- script_map->AppendDescriptor(&d, witness);
+ script_map->AppendDescriptor(&d);
}
{
CallbacksDescriptor d(factory()->name_string(), script_name, attribs);
- script_map->AppendDescriptor(&d, witness);
+ script_map->AppendDescriptor(&d);
}
{
CallbacksDescriptor d(id_string, script_id, attribs);
- script_map->AppendDescriptor(&d, witness);
+ script_map->AppendDescriptor(&d);
}
{
CallbacksDescriptor d(line_offset_string, script_line_offset, attribs);
- script_map->AppendDescriptor(&d, witness);
+ script_map->AppendDescriptor(&d);
}
{
CallbacksDescriptor d(
column_offset_string, script_column_offset, attribs);
- script_map->AppendDescriptor(&d, witness);
+ script_map->AppendDescriptor(&d);
}
{
CallbacksDescriptor d(type_string, script_type, attribs);
- script_map->AppendDescriptor(&d, witness);
+ script_map->AppendDescriptor(&d);
}
{
CallbacksDescriptor d(
compilation_type_string, script_compilation_type, attribs);
- script_map->AppendDescriptor(&d, witness);
+ script_map->AppendDescriptor(&d);
}
{
CallbacksDescriptor d(line_ends_string, script_line_ends, attribs);
- script_map->AppendDescriptor(&d, witness);
+ script_map->AppendDescriptor(&d);
}
{
CallbacksDescriptor d(
context_data_string, script_context_data, attribs);
- script_map->AppendDescriptor(&d, witness);
+ script_map->AppendDescriptor(&d);
}
{
CallbacksDescriptor d(
eval_from_script_string, script_eval_from_script, attribs);
- script_map->AppendDescriptor(&d, witness);
+ script_map->AppendDescriptor(&d);
}
{
@@ -1819,7 +1792,7 @@
eval_from_script_position_string,
script_eval_from_script_position,
attribs);
- script_map->AppendDescriptor(&d, witness);
+ script_map->AppendDescriptor(&d);
}
{
@@ -1827,7 +1800,7 @@
eval_from_function_name_string,
script_eval_from_function_name,
attribs);
- script_map->AppendDescriptor(&d, witness);
+ script_map->AppendDescriptor(&d);
}
// Allocate the empty script.
@@ -1895,7 +1868,7 @@
{ Handle<String> key = factory()->function_class_string();
Handle<JSFunction> function =
Handle<JSFunction>::cast(Object::GetProperty(
- isolate()->global_object(), key));
+ isolate()->global_object(), key).ToHandleChecked());
Handle<JSObject> proto =
Handle<JSObject>(JSObject::cast(function->instance_prototype()));
@@ -1947,10 +1920,7 @@
initial_map->set_prototype(*array_prototype);
// Update map with length accessor from Array and add "index" and "input".
- Handle<DescriptorArray> reresult_descriptors =
- factory()->NewDescriptorArray(0, 3);
- DescriptorArray::WhitenessWitness witness(*reresult_descriptors);
- initial_map->set_instance_descriptors(*reresult_descriptors);
+ Map::EnsureDescriptorSlack(initial_map, 3);
{
JSFunction* array_function = native_context()->array_function();
@@ -1964,14 +1934,14 @@
handle(array_descriptors->GetValue(old),
isolate()),
array_descriptors->GetDetails(old).attributes());
- initial_map->AppendDescriptor(&desc, witness);
+ initial_map->AppendDescriptor(&desc);
}
{
FieldDescriptor index_field(factory()->index_string(),
JSRegExpResult::kIndexIndex,
NONE,
Representation::Tagged());
- initial_map->AppendDescriptor(&index_field, witness);
+ initial_map->AppendDescriptor(&index_field);
}
{
@@ -1979,7 +1949,7 @@
JSRegExpResult::kInputIndex,
NONE,
Representation::Tagged());
- initial_map->AppendDescriptor(&input_field, witness);
+ initial_map->AppendDescriptor(&input_field);
}
initial_map->set_inobject_properties(2);
@@ -2044,7 +2014,7 @@
Handle<String> property_string = factory->InternalizeUtf8String(property);
ASSERT(!property_string.is_null());
Handle<JSFunction> function = Handle<JSFunction>::cast(
- Object::GetProperty(global, property_string));
+ Object::GetProperty(global, property_string).ToHandleChecked());
return Handle<JSObject>(JSObject::cast(function->prototype()));
}
@@ -2054,8 +2024,8 @@
BuiltinFunctionId id) {
Factory* factory = holder->GetIsolate()->factory();
Handle<String> name = factory->InternalizeUtf8String(function_name);
- Handle<Object> function_object = Object::GetProperty(holder, name);
- ASSERT(!function_object.is_null());
+ Handle<Object> function_object =
+ Object::GetProperty(holder, name).ToHandleChecked();
Handle<JSFunction> function = Handle<JSFunction>::cast(function_object);
function->shared()->set_function_data(Smi::FromInt(id));
}
@@ -2351,7 +2321,7 @@
Handle<String> name =
factory()->InternalizeUtf8String(Builtins::GetName(id));
Handle<Object> function_object =
- GlobalObject::GetPropertyNoExceptionThrown(builtins, name);
+ Object::GetProperty(builtins, name).ToHandleChecked();
Handle<JSFunction> function = Handle<JSFunction>::cast(function_object);
builtins->set_javascript_builtin(id, *function);
if (!Compiler::EnsureCompiled(function, CLEAR_EXCEPTION)) {
@@ -2401,10 +2371,10 @@
ASSERT(FunctionTemplateInfo::cast(object_template->constructor())
->IsTemplateFor(object->map()));;
- bool pending_exception = false;
- Handle<JSObject> obj =
- Execution::InstantiateObject(object_template, &pending_exception);
- if (pending_exception) {
+ MaybeHandle<JSObject> maybe_obj =
+ Execution::InstantiateObject(object_template);
+ Handle<JSObject> obj;
+ if (!maybe_obj.ToHandle(&obj)) {
ASSERT(isolate()->has_pending_exception());
isolate()->clear_pending_exception();
return false;
diff --git a/src/builtins.cc b/src/builtins.cc
index 054963d..3f81086 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -381,14 +381,14 @@
for (int i = 0; i < argc; ++i) {
argv[i] = args.at<Object>(i + 1);
}
- bool pending_exception;
- Handle<Object> result = Execution::Call(isolate,
- function,
- args.receiver(),
- argc,
- argv.start(),
- &pending_exception);
- if (pending_exception) return Failure::Exception();
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ Execution::Call(isolate,
+ function,
+ args.receiver(),
+ argc,
+ argv.start()));
return *result;
}
@@ -1174,15 +1174,13 @@
Handle<JSFunction> function = args.called_function();
ASSERT(function->shared()->IsApiFunction());
- FunctionTemplateInfo* fun_data = function->shared()->get_api_func_data();
+ Handle<FunctionTemplateInfo> fun_data(
+ function->shared()->get_api_func_data(), isolate);
if (is_construct) {
- Handle<FunctionTemplateInfo> desc(fun_data, isolate);
- bool pending_exception = false;
- isolate->factory()->ConfigureInstance(
- desc, Handle<JSObject>::cast(args.receiver()), &pending_exception);
- ASSERT(isolate->has_pending_exception() == pending_exception);
- if (pending_exception) return Failure::Exception();
- fun_data = *desc;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, fun_data,
+ isolate->factory()->ConfigureInstance(
+ fun_data, Handle<JSObject>::cast(args.receiver())));
}
SharedFunctionInfo* shared = function->shared();
@@ -1194,7 +1192,7 @@
}
}
- Object* raw_holder = TypeCheck(heap, args.length(), &args[0], fun_data);
+ Object* raw_holder = TypeCheck(heap, args.length(), &args[0], *fun_data);
if (raw_holder->IsNull()) {
// This function cannot be called with the given receiver. Abort!
diff --git a/src/code-stubs.cc b/src/code-stubs.cc
index 0620362..0840f6c 100644
--- a/src/code-stubs.cc
+++ b/src/code-stubs.cc
@@ -72,10 +72,11 @@
}
-void CodeStub::RecordCodeGeneration(Code* code, Isolate* isolate) {
+void CodeStub::RecordCodeGeneration(Handle<Code> code, Isolate* isolate) {
+ IC::RegisterWeakMapDependency(code);
SmartArrayPointer<const char> name = GetName();
- PROFILE(isolate, CodeCreateEvent(Logger::STUB_TAG, code, name.get()));
- GDBJIT(AddCode(GDBJITInterface::STUB, name.get(), code));
+ PROFILE(isolate, CodeCreateEvent(Logger::STUB_TAG, *code, name.get()));
+ GDBJIT(AddCode(GDBJITInterface::STUB, name.get(), *code));
Counters* counters = isolate->counters();
counters->total_stubs_code_size()->Increment(code->instruction_size());
}
@@ -91,7 +92,7 @@
Handle<Code> ic = GetCode(isolate);
ic = isolate->factory()->CopyCode(ic);
ic->FindAndReplace(pattern);
- RecordCodeGeneration(*ic, isolate);
+ RecordCodeGeneration(ic, isolate);
return ic;
}
@@ -154,7 +155,7 @@
Handle<Code> new_object = GenerateCode(isolate);
new_object->set_major_key(MajorKey());
FinishCode(new_object);
- RecordCodeGeneration(*new_object, isolate);
+ RecordCodeGeneration(new_object, isolate);
#ifdef ENABLE_DISASSEMBLER
if (FLAG_print_code_stubs) {
diff --git a/src/code-stubs.h b/src/code-stubs.h
index 6a04f67..ed08fcf 100644
--- a/src/code-stubs.h
+++ b/src/code-stubs.h
@@ -228,7 +228,7 @@
private:
// Perform bookkeeping required after code generation when stub code is
// initially generated.
- void RecordCodeGeneration(Code* code, Isolate* isolate);
+ void RecordCodeGeneration(Handle<Code> code, Isolate* isolate);
// Finish the code object after it has been generated.
virtual void FinishCode(Handle<Code> code) { }
diff --git a/src/compilation-cache.cc b/src/compilation-cache.cc
index 64c1116..8f398e3 100644
--- a/src/compilation-cache.cc
+++ b/src/compilation-cache.cc
@@ -161,7 +161,8 @@
// Were both scripts tagged by the embedder as being shared cross-origin?
if (is_shared_cross_origin != script->is_shared_cross_origin()) return false;
// Compare the two name strings for equality.
- return String::cast(*name)->Equals(String::cast(script->name()));
+ return String::Equals(Handle<String>::cast(name),
+ Handle<String>(String::cast(script->name())));
}
diff --git a/src/compiler.cc b/src/compiler.cc
index 7be6c4d..1234639 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -928,7 +928,7 @@
bool is_shared_cross_origin,
Handle<Context> context,
v8::Extension* extension,
- ScriptDataImpl** cached_data,
+ ScriptData** cached_data,
CachedDataMode cached_data_mode,
NativesFlag natives) {
if (cached_data_mode == NO_CACHED_DATA) {
diff --git a/src/compiler.h b/src/compiler.h
index 3802016..4bdb7ae 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -35,7 +35,7 @@
namespace v8 {
namespace internal {
-class ScriptDataImpl;
+class ScriptData;
class HydrogenCodeStub;
// ParseRestriction is used to restrict the set of valid statements in a
@@ -83,7 +83,7 @@
Handle<Script> script() const { return script_; }
HydrogenCodeStub* code_stub() const {return code_stub_; }
v8::Extension* extension() const { return extension_; }
- ScriptDataImpl** cached_data() const { return cached_data_; }
+ ScriptData** cached_data() const { return cached_data_; }
CachedDataMode cached_data_mode() const {
return cached_data_mode_;
}
@@ -189,7 +189,7 @@
ASSERT(!is_lazy());
extension_ = extension;
}
- void SetCachedData(ScriptDataImpl** cached_data,
+ void SetCachedData(ScriptData** cached_data,
CachedDataMode cached_data_mode) {
cached_data_mode_ = cached_data_mode;
if (cached_data_mode == NO_CACHED_DATA) {
@@ -412,7 +412,7 @@
// Fields possibly needed for eager compilation, NULL by default.
v8::Extension* extension_;
- ScriptDataImpl** cached_data_;
+ ScriptData** cached_data_;
CachedDataMode cached_data_mode_;
// The context of the caller for eval code, and the global context for a
@@ -641,7 +641,7 @@
bool is_shared_cross_origin,
Handle<Context> context,
v8::Extension* extension,
- ScriptDataImpl** cached_data,
+ ScriptData** cached_data,
CachedDataMode cached_data_mode,
NativesFlag is_natives_code);
diff --git a/src/contexts.cc b/src/contexts.cc
index 33d47e9..5ee0d4b 100644
--- a/src/contexts.cc
+++ b/src/contexts.cc
@@ -231,7 +231,7 @@
} else if (context->IsCatchContext()) {
// Catch contexts have the variable name in the extension slot.
- if (name->Equals(String::cast(context->extension()))) {
+ if (String::Equals(name, handle(String::cast(context->extension())))) {
if (FLAG_trace_contexts) {
PrintF("=> found in catch context\n");
}
diff --git a/src/conversions.cc b/src/conversions.cc
index 9c52d41..1d5ed35 100644
--- a/src/conversions.cc
+++ b/src/conversions.cc
@@ -56,7 +56,7 @@
double StringToDouble(UnicodeCache* unicode_cache,
- Vector<const char> str,
+ Vector<const uint8_t> str,
int flags,
double empty_string_val) {
// We cast to const uint8_t* here to avoid instantiating the
@@ -78,6 +78,23 @@
}
+// Converts a string into an integer.
+double StringToInt(UnicodeCache* unicode_cache,
+ Vector<const uint8_t> vector,
+ int radix) {
+ return InternalStringToInt(
+ unicode_cache, vector.start(), vector.start() + vector.length(), radix);
+}
+
+
+double StringToInt(UnicodeCache* unicode_cache,
+ Vector<const uc16> vector,
+ int radix) {
+ return InternalStringToInt(
+ unicode_cache, vector.start(), vector.start() + vector.length(), radix);
+}
+
+
const char* DoubleToCString(double v, Vector<char> buffer) {
switch (fpclassify(v)) {
case FP_NAN: return "NaN";
diff --git a/src/conversions.h b/src/conversions.h
index f850f58..c8484e4 100644
--- a/src/conversions.h
+++ b/src/conversions.h
@@ -122,7 +122,7 @@
// Converts a string into a double value according to ECMA-262 9.3.1
double StringToDouble(UnicodeCache* unicode_cache,
- Vector<const char> str,
+ Vector<const uint8_t> str,
int flags,
double empty_string_val = 0);
double StringToDouble(UnicodeCache* unicode_cache,
@@ -135,6 +135,16 @@
int flags,
double empty_string_val = 0);
+// Converts a string into an integer.
+double StringToInt(UnicodeCache* unicode_cache,
+ Vector<const uint8_t> vector,
+ int radix);
+
+
+double StringToInt(UnicodeCache* unicode_cache,
+ Vector<const uc16> vector,
+ int radix);
+
const int kDoubleToCStringMinBufferSize = 100;
// Converts a double to a string value according to ECMA-262 9.8.1.
diff --git a/src/debug-debugger.js b/src/debug-debugger.js
index b159ae3..d759fe5 100644
--- a/src/debug-debugger.js
+++ b/src/debug-debugger.js
@@ -1217,31 +1217,6 @@
};
-function MakeNewFunctionEvent(func) {
- return new NewFunctionEvent(func);
-}
-
-
-function NewFunctionEvent(func) {
- this.func = func;
-}
-
-
-NewFunctionEvent.prototype.eventType = function() {
- return Debug.DebugEvent.NewFunction;
-};
-
-
-NewFunctionEvent.prototype.name = function() {
- return this.func.name;
-};
-
-
-NewFunctionEvent.prototype.setBreakPoint = function(p) {
- Debug.setBreakPoint(this.func, p || 0);
-};
-
-
function MakeScriptCollectedEvent(exec_state, id) {
return new ScriptCollectedEvent(exec_state, id);
}
diff --git a/src/debug.cc b/src/debug.cc
index 75c7282..41c608a 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -774,19 +774,19 @@
}
// Execute the shared function in the debugger context.
- bool caught_exception;
Handle<JSFunction> function =
factory->NewFunctionFromSharedFunctionInfo(function_info, context);
- Handle<Object> exception =
+ Handle<Object> exception;
+ MaybeHandle<Object> result =
Execution::TryCall(function,
Handle<Object>(context->global_object(), isolate),
0,
NULL,
- &caught_exception);
+ &exception);
// Check for caught exceptions.
- if (caught_exception) {
+ if (result.is_null()) {
ASSERT(!isolate->has_pending_exception());
MessageLocation computed_location;
isolate->ComputeLocation(&computed_location);
@@ -1118,29 +1118,25 @@
STATIC_ASCII_VECTOR("IsBreakPointTriggered"));
Handle<GlobalObject> debug_global(debug_context()->global_object());
Handle<JSFunction> check_break_point =
- Handle<JSFunction>::cast(GlobalObject::GetPropertyNoExceptionThrown(
- debug_global, is_break_point_triggered_string));
+ Handle<JSFunction>::cast(Object::GetProperty(
+ debug_global, is_break_point_triggered_string).ToHandleChecked());
// Get the break id as an object.
Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id());
// Call HandleBreakPointx.
- bool caught_exception;
Handle<Object> argv[] = { break_id, break_point_object };
- Handle<Object> result = Execution::TryCall(check_break_point,
- isolate_->js_builtins_object(),
- ARRAY_SIZE(argv),
- argv,
- &caught_exception);
-
- // If exception or non boolean result handle as not triggered
- if (caught_exception || !result->IsBoolean()) {
- return false;
- }
+ Handle<Object> result;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate_, result,
+ Execution::TryCall(check_break_point,
+ isolate_->js_builtins_object(),
+ ARRAY_SIZE(argv),
+ argv),
+ false);
// Return whether the break point is triggered.
- ASSERT(!result.is_null());
- return (*result)->IsTrue();
+ return result->IsTrue();
}
@@ -2463,13 +2459,14 @@
// Clear the mirror cache.
Handle<String> function_name = isolate_->factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR("ClearMirrorCache"));
- Handle<Object> fun = GlobalObject::GetPropertyNoExceptionThrown(
- isolate_->global_object(), function_name);
+ Handle<Object> fun = Object::GetProperty(
+ isolate_->global_object(), function_name).ToHandleChecked();
ASSERT(fun->IsJSFunction());
- bool caught_exception;
- Execution::TryCall(Handle<JSFunction>::cast(fun),
+ Execution::TryCall(
+ Handle<JSFunction>::cast(fun),
Handle<JSObject>(Debug::debug_context()->global_object()),
- 0, NULL, &caught_exception);
+ 0,
+ NULL);
}
@@ -2590,112 +2587,85 @@
Debugger::~Debugger() {}
-Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name,
- int argc,
- Handle<Object> argv[],
- bool* caught_exception) {
+MaybeHandle<Object> Debugger::MakeJSObject(
+ Vector<const char> constructor_name,
+ int argc,
+ Handle<Object> argv[]) {
ASSERT(isolate_->context() == *isolate_->debug()->debug_context());
// Create the execution state object.
Handle<String> constructor_str =
isolate_->factory()->InternalizeUtf8String(constructor_name);
ASSERT(!constructor_str.is_null());
- Handle<Object> constructor = GlobalObject::GetPropertyNoExceptionThrown(
- isolate_->global_object(), constructor_str);
+ Handle<Object> constructor = Object::GetProperty(
+ isolate_->global_object(), constructor_str).ToHandleChecked();
ASSERT(constructor->IsJSFunction());
- if (!constructor->IsJSFunction()) {
- *caught_exception = true;
- return isolate_->factory()->undefined_value();
- }
- Handle<Object> js_object = Execution::TryCall(
+ if (!constructor->IsJSFunction()) return MaybeHandle<Object>();
+ return Execution::TryCall(
Handle<JSFunction>::cast(constructor),
Handle<JSObject>(isolate_->debug()->debug_context()->global_object()),
argc,
- argv,
- caught_exception);
- return js_object;
+ argv);
}
-Handle<Object> Debugger::MakeExecutionState(bool* caught_exception) {
+MaybeHandle<Object> Debugger::MakeExecutionState() {
// Create the execution state object.
Handle<Object> break_id = isolate_->factory()->NewNumberFromInt(
isolate_->debug()->break_id());
Handle<Object> argv[] = { break_id };
- return MakeJSObject(CStrVector("MakeExecutionState"),
- ARRAY_SIZE(argv),
- argv,
- caught_exception);
+ return MakeJSObject(CStrVector("MakeExecutionState"), ARRAY_SIZE(argv), argv);
}
-Handle<Object> Debugger::MakeBreakEvent(Handle<Object> exec_state,
- Handle<Object> break_points_hit,
- bool* caught_exception) {
+MaybeHandle<Object> Debugger::MakeBreakEvent(Handle<Object> break_points_hit) {
+ Handle<Object> exec_state;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate_, exec_state, MakeExecutionState(), Object);
// Create the new break event object.
Handle<Object> argv[] = { exec_state, break_points_hit };
- return MakeJSObject(CStrVector("MakeBreakEvent"),
- ARRAY_SIZE(argv),
- argv,
- caught_exception);
+ return MakeJSObject(CStrVector("MakeBreakEvent"), ARRAY_SIZE(argv), argv);
}
-Handle<Object> Debugger::MakeExceptionEvent(Handle<Object> exec_state,
- Handle<Object> exception,
- bool uncaught,
- bool* caught_exception) {
- Factory* factory = isolate_->factory();
+MaybeHandle<Object> Debugger::MakeExceptionEvent(Handle<Object> exception,
+ bool uncaught) {
+ Handle<Object> exec_state;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate_, exec_state, MakeExecutionState(), Object);
// Create the new exception event object.
Handle<Object> argv[] = { exec_state,
exception,
- factory->ToBoolean(uncaught) };
- return MakeJSObject(CStrVector("MakeExceptionEvent"),
- ARRAY_SIZE(argv),
- argv,
- caught_exception);
+ isolate_->factory()->ToBoolean(uncaught) };
+ return MakeJSObject(CStrVector("MakeExceptionEvent"), ARRAY_SIZE(argv), argv);
}
-Handle<Object> Debugger::MakeNewFunctionEvent(Handle<Object> function,
- bool* caught_exception) {
- // Create the new function event object.
- Handle<Object> argv[] = { function };
- return MakeJSObject(CStrVector("MakeNewFunctionEvent"),
- ARRAY_SIZE(argv),
- argv,
- caught_exception);
-}
-
-
-Handle<Object> Debugger::MakeCompileEvent(Handle<Script> script,
- bool before,
- bool* caught_exception) {
+MaybeHandle<Object> Debugger::MakeCompileEvent(Handle<Script> script,
+ bool before) {
Factory* factory = isolate_->factory();
// Create the compile event object.
- Handle<Object> exec_state = MakeExecutionState(caught_exception);
+ Handle<Object> exec_state;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate_, exec_state, MakeExecutionState(), Object);
Handle<Object> script_wrapper = GetScriptWrapper(script);
Handle<Object> argv[] = { exec_state,
script_wrapper,
factory->ToBoolean(before) };
- return MakeJSObject(CStrVector("MakeCompileEvent"),
- ARRAY_SIZE(argv),
- argv,
- caught_exception);
+ return MakeJSObject(CStrVector("MakeCompileEvent"), ARRAY_SIZE(argv), argv);
}
-Handle<Object> Debugger::MakeScriptCollectedEvent(int id,
- bool* caught_exception) {
+MaybeHandle<Object> Debugger::MakeScriptCollectedEvent(int id) {
// Create the script collected event object.
- Handle<Object> exec_state = MakeExecutionState(caught_exception);
+ Handle<Object> exec_state;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate_, exec_state, MakeExecutionState(), Object);
Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id), isolate_);
Handle<Object> argv[] = { exec_state, id_object };
- return MakeJSObject(CStrVector("MakeScriptCollectedEvent"),
- ARRAY_SIZE(argv),
- argv,
- caught_exception);
+ return MakeJSObject(
+ CStrVector("MakeScriptCollectedEvent"), ARRAY_SIZE(argv), argv);
}
@@ -2724,17 +2694,11 @@
// Clear all current stepping setup.
debug->ClearStepping();
// Create the event data object.
- bool caught_exception = false;
- Handle<Object> exec_state = MakeExecutionState(&caught_exception);
Handle<Object> event_data;
- if (!caught_exception) {
- event_data = MakeExceptionEvent(exec_state, exception, uncaught,
- &caught_exception);
- }
// Bail out and don't call debugger if exception.
- if (caught_exception) {
- return;
- }
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate_, event_data, MakeExceptionEvent(exception, uncaught),
+ /* void */ ;);
// Process debug event.
ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false);
@@ -2756,17 +2720,10 @@
ASSERT(isolate_->context() == *isolate_->debug()->debug_context());
// Create the event data object.
- bool caught_exception = false;
- Handle<Object> exec_state = MakeExecutionState(&caught_exception);
Handle<Object> event_data;
- if (!caught_exception) {
- event_data = MakeBreakEvent(exec_state, break_points_hit,
- &caught_exception);
- }
// Bail out and don't call debugger if exception.
- if (caught_exception) {
- return;
- }
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate_, event_data, MakeBreakEvent(break_points_hit), /* void */ ;);
// Process debug event.
ProcessDebugEvent(v8::Break,
@@ -2788,12 +2745,10 @@
if (debugger.FailedToEnter()) return;
// Create the event data object.
- bool caught_exception = false;
- Handle<Object> event_data = MakeCompileEvent(script, true, &caught_exception);
+ Handle<Object> event_data;
// Bail out and don't call debugger if exception.
- if (caught_exception) {
- return;
- }
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate_, event_data, MakeCompileEvent(script, true), /* void */ ;);
// Process debug event.
ProcessDebugEvent(v8::BeforeCompile,
@@ -2833,8 +2788,8 @@
STATIC_ASCII_VECTOR("UpdateScriptBreakPoints"));
Handle<GlobalObject> debug_global(debug->debug_context()->global_object());
Handle<Object> update_script_break_points =
- GlobalObject::GetPropertyNoExceptionThrown(
- debug_global, update_script_break_points_string);
+ Object::GetProperty(
+ debug_global, update_script_break_points_string).ToHandleChecked();
if (!update_script_break_points->IsJSFunction()) {
return;
}
@@ -2845,14 +2800,11 @@
Handle<JSValue> wrapper = GetScriptWrapper(script);
// Call UpdateScriptBreakPoints expect no exceptions.
- bool caught_exception;
Handle<Object> argv[] = { wrapper };
- Execution::TryCall(Handle<JSFunction>::cast(update_script_break_points),
- isolate_->js_builtins_object(),
- ARRAY_SIZE(argv),
- argv,
- &caught_exception);
- if (caught_exception) {
+ if (Execution::TryCall(Handle<JSFunction>::cast(update_script_break_points),
+ isolate_->js_builtins_object(),
+ ARRAY_SIZE(argv),
+ argv).is_null()) {
return;
}
// Bail out based on state or if there is no listener for this event
@@ -2860,17 +2812,13 @@
if (!Debugger::EventActive(v8::AfterCompile)) return;
// Create the compile state object.
- Handle<Object> event_data = MakeCompileEvent(script,
- false,
- &caught_exception);
+ Handle<Object> event_data;
// Bail out and don't call debugger if exception.
- if (caught_exception) {
- return;
- }
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate_, event_data, MakeCompileEvent(script, false), /* void */ ;);
+
// Process debug event.
- ProcessDebugEvent(v8::AfterCompile,
- Handle<JSObject>::cast(event_data),
- true);
+ ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true);
}
@@ -2887,13 +2835,10 @@
if (debugger.FailedToEnter()) return;
// Create the script collected state object.
- bool caught_exception = false;
- Handle<Object> event_data = MakeScriptCollectedEvent(id,
- &caught_exception);
+ Handle<Object> event_data;
// Bail out and don't call debugger if exception.
- if (caught_exception) {
- return;
- }
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate_, event_data, MakeScriptCollectedEvent(id), /* void */ ;);
// Process debug event.
ProcessDebugEvent(v8::ScriptCollected,
@@ -2913,11 +2858,10 @@
}
// Create the execution state.
- bool caught_exception = false;
- Handle<Object> exec_state = MakeExecutionState(&caught_exception);
- if (caught_exception) {
- return;
- }
+ Handle<Object> exec_state;
+ // Bail out and don't call debugger if exception.
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate_, exec_state, MakeExecutionState(), /* void */ ;);
// First notify the message handler if any.
if (message_handler_ != NULL) {
NotifyMessageHandler(event,
@@ -2988,12 +2932,10 @@
exec_state,
event_data,
event_listener_data_ };
- bool caught_exception;
Execution::TryCall(fun,
isolate_->global_object(),
ARRAY_SIZE(argv),
- argv,
- &caught_exception);
+ argv);
// Silently ignore exceptions from debug event listeners.
}
@@ -3347,9 +3289,8 @@
}
-Handle<Object> Debugger::Call(Handle<JSFunction> fun,
- Handle<Object> data,
- bool* pending_exception) {
+MaybeHandle<Object> Debugger::Call(Handle<JSFunction> fun,
+ Handle<Object> data) {
// When calling functions in the debugger prevent it from beeing unloaded.
Debugger::never_unload_debugger_ = true;
@@ -3360,22 +3301,20 @@
}
// Create the execution state.
- bool caught_exception = false;
- Handle<Object> exec_state = MakeExecutionState(&caught_exception);
- if (caught_exception) {
- return isolate_->factory()->undefined_value();
- }
+ Handle<Object> exec_state;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate_, exec_state,
+ MakeExecutionState(),
+ isolate_->factory()->undefined_value());
Handle<Object> argv[] = { exec_state, data };
- Handle<Object> result = Execution::Call(
+ return Execution::Call(
isolate_,
fun,
Handle<Object>(isolate_->debug()->debug_context_->global_proxy(),
isolate_),
ARRAY_SIZE(argv),
- argv,
- pending_exception);
- return result;
+ argv);
}
@@ -3594,8 +3533,8 @@
v8::Handle<v8::String> MessageImpl::GetJSON() const {
- v8::EscapableHandleScope scope(
- reinterpret_cast<v8::Isolate*>(event_data_->GetIsolate()));
+ Isolate* isolate = event_data_->GetIsolate();
+ v8::EscapableHandleScope scope(reinterpret_cast<v8::Isolate*>(isolate));
if (IsEvent()) {
// Call toJSONProtocol on the debug event object.
@@ -3604,11 +3543,11 @@
if (!fun->IsJSFunction()) {
return v8::Handle<v8::String>();
}
- bool caught_exception;
- Handle<Object> json = Execution::TryCall(Handle<JSFunction>::cast(fun),
- event_data_,
- 0, NULL, &caught_exception);
- if (caught_exception || !json->IsString()) {
+
+ MaybeHandle<Object> maybe_json =
+ Execution::TryCall(Handle<JSFunction>::cast(fun), event_data_, 0, NULL);
+ Handle<Object> json;
+ if (!maybe_json.ToHandle(&json) || !json->IsString()) {
return v8::Handle<v8::String>();
}
return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json)));
diff --git a/src/debug.h b/src/debug.h
index 564f9e8..8a793a7 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -786,25 +786,19 @@
void DebugRequest(const uint16_t* json_request, int length);
- Handle<Object> MakeJSObject(Vector<const char> constructor_name,
- int argc,
- Handle<Object> argv[],
- bool* caught_exception);
- Handle<Object> MakeExecutionState(bool* caught_exception);
- Handle<Object> MakeBreakEvent(Handle<Object> exec_state,
- Handle<Object> break_points_hit,
- bool* caught_exception);
- Handle<Object> MakeExceptionEvent(Handle<Object> exec_state,
- Handle<Object> exception,
- bool uncaught,
- bool* caught_exception);
- Handle<Object> MakeNewFunctionEvent(Handle<Object> func,
- bool* caught_exception);
- Handle<Object> MakeCompileEvent(Handle<Script> script,
- bool before,
- bool* caught_exception);
- Handle<Object> MakeScriptCollectedEvent(int id,
- bool* caught_exception);
+ MUST_USE_RESULT MaybeHandle<Object> MakeJSObject(
+ Vector<const char> constructor_name,
+ int argc,
+ Handle<Object> argv[]);
+ MUST_USE_RESULT MaybeHandle<Object> MakeExecutionState();
+ MUST_USE_RESULT MaybeHandle<Object> MakeBreakEvent(
+ Handle<Object> break_points_hit);
+ MUST_USE_RESULT MaybeHandle<Object> MakeExceptionEvent(
+ Handle<Object> exception, bool uncaught);
+ MUST_USE_RESULT MaybeHandle<Object> MakeCompileEvent(
+ Handle<Script> script, bool before);
+ MUST_USE_RESULT MaybeHandle<Object> MakeScriptCollectedEvent(int id);
+
void OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue);
void OnException(Handle<Object> exception, bool uncaught);
void OnBeforeCompile(Handle<Script> script);
@@ -844,9 +838,8 @@
// Enqueue a debugger command to the command queue for event listeners.
void EnqueueDebugCommand(v8::Debug::ClientData* client_data = NULL);
- Handle<Object> Call(Handle<JSFunction> fun,
- Handle<Object> data,
- bool* pending_exception);
+ MUST_USE_RESULT MaybeHandle<Object> Call(Handle<JSFunction> fun,
+ Handle<Object> data);
// Start the debugger agent listening on the provided port.
bool StartAgent(const char* name, int port,
diff --git a/src/execution.cc b/src/execution.cc
index 2e16413..2e6023b 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -36,12 +36,12 @@
}
-static Handle<Object> Invoke(bool is_construct,
- Handle<JSFunction> function,
- Handle<Object> receiver,
- int argc,
- Handle<Object> args[],
- bool* has_pending_exception) {
+MUST_USE_RESULT static MaybeHandle<Object> Invoke(
+ bool is_construct,
+ Handle<JSFunction> function,
+ Handle<Object> receiver,
+ int argc,
+ Handle<Object> args[]) {
Isolate* isolate = function->GetIsolate();
// Entering JavaScript.
@@ -49,9 +49,8 @@
CHECK(AllowJavascriptExecution::IsAllowed(isolate));
if (!ThrowOnJavascriptExecution::IsAllowed(isolate)) {
isolate->ThrowIllegalOperation();
- *has_pending_exception = true;
isolate->ReportPendingMessages();
- return Handle<Object>();
+ return MaybeHandle<Object>();
}
// Placeholder for return value.
@@ -100,9 +99,9 @@
#endif
// Update the pending exception flag and return the value.
- *has_pending_exception = value->IsException();
- ASSERT(*has_pending_exception == isolate->has_pending_exception());
- if (*has_pending_exception) {
+ bool has_exception = value->IsException();
+ ASSERT(has_exception == isolate->has_pending_exception());
+ if (has_exception) {
isolate->ReportPendingMessages();
#ifdef ENABLE_DEBUGGER_SUPPORT
// Reset stepping state when script exits with uncaught exception.
@@ -110,7 +109,7 @@
isolate->debug()->ClearStepping();
}
#endif // ENABLE_DEBUGGER_SUPPORT
- return Handle<Object>();
+ return MaybeHandle<Object>();
} else {
isolate->clear_pending_message();
}
@@ -119,18 +118,15 @@
}
-Handle<Object> Execution::Call(Isolate* isolate,
- Handle<Object> callable,
- Handle<Object> receiver,
- int argc,
- Handle<Object> argv[],
- bool* pending_exception,
- bool convert_receiver) {
- *pending_exception = false;
-
+MaybeHandle<Object> Execution::Call(Isolate* isolate,
+ Handle<Object> callable,
+ Handle<Object> receiver,
+ int argc,
+ Handle<Object> argv[],
+ bool convert_receiver) {
if (!callable->IsJSFunction()) {
- callable = TryGetFunctionDelegate(isolate, callable, pending_exception);
- if (*pending_exception) return callable;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, callable, TryGetFunctionDelegate(isolate, callable), Object);
}
Handle<JSFunction> func = Handle<JSFunction>::cast(callable);
@@ -147,29 +143,27 @@
receiver = Handle<Object>(global, func->GetIsolate());
}
} else {
- receiver = ToObject(isolate, receiver, pending_exception);
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, receiver, ToObject(isolate, receiver), Object);
}
- if (*pending_exception) return callable;
}
- return Invoke(false, func, receiver, argc, argv, pending_exception);
+ return Invoke(false, func, receiver, argc, argv);
}
-Handle<Object> Execution::New(Handle<JSFunction> func,
- int argc,
- Handle<Object> argv[],
- bool* pending_exception) {
- return Invoke(true, func, func->GetIsolate()->global_object(), argc, argv,
- pending_exception);
+MaybeHandle<Object> Execution::New(Handle<JSFunction> func,
+ int argc,
+ Handle<Object> argv[]) {
+ return Invoke(true, func, func->GetIsolate()->global_object(), argc, argv);
}
-Handle<Object> Execution::TryCall(Handle<JSFunction> func,
- Handle<Object> receiver,
- int argc,
- Handle<Object> args[],
- bool* caught_exception) {
+MaybeHandle<Object> Execution::TryCall(Handle<JSFunction> func,
+ Handle<Object> receiver,
+ int argc,
+ Handle<Object> args[],
+ Handle<Object>* exception_out) {
// Enter a try-block while executing the JavaScript code. To avoid
// duplicate error printing it must be non-verbose. Also, to avoid
// creating message objects during stack overflow we shouldn't
@@ -177,30 +171,30 @@
v8::TryCatch catcher;
catcher.SetVerbose(false);
catcher.SetCaptureMessage(false);
- *caught_exception = false;
// Get isolate now, because handle might be persistent
// and get destroyed in the next call.
Isolate* isolate = func->GetIsolate();
- Handle<Object> result = Invoke(false, func, receiver, argc, args,
- caught_exception);
+ MaybeHandle<Object> maybe_result = Invoke(false, func, receiver, argc, args);
- if (*caught_exception) {
+ if (maybe_result.is_null()) {
ASSERT(catcher.HasCaught());
ASSERT(isolate->has_pending_exception());
ASSERT(isolate->external_caught_exception());
- if (isolate->pending_exception() ==
- isolate->heap()->termination_exception()) {
- result = isolate->factory()->termination_exception();
- } else {
- result = v8::Utils::OpenHandle(*catcher.Exception());
+ if (exception_out != NULL) {
+ if (isolate->pending_exception() ==
+ isolate->heap()->termination_exception()) {
+ *exception_out = isolate->factory()->termination_exception();
+ } else {
+ *exception_out = v8::Utils::OpenHandle(*catcher.Exception());
+ }
}
isolate->OptionalRescheduleException(true);
}
ASSERT(!isolate->has_pending_exception());
ASSERT(!isolate->external_caught_exception());
- return result;
+ return maybe_result;
}
@@ -231,9 +225,8 @@
}
-Handle<Object> Execution::TryGetFunctionDelegate(Isolate* isolate,
- Handle<Object> object,
- bool* has_pending_exception) {
+MaybeHandle<Object> Execution::TryGetFunctionDelegate(Isolate* isolate,
+ Handle<Object> object) {
ASSERT(!object->IsJSFunction());
// If object is a function proxy, get its handler. Iterate if necessary.
@@ -255,10 +248,8 @@
// throw a non-callable exception.
i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError(
"called_non_callable", i::HandleVector<i::Object>(&object, 1));
- isolate->Throw(*error_obj);
- *has_pending_exception = true;
- return isolate->factory()->undefined_value();
+ return isolate->Throw<Object>(error_obj);
}
@@ -288,10 +279,8 @@
}
-Handle<Object> Execution::TryGetConstructorDelegate(
- Isolate* isolate,
- Handle<Object> object,
- bool* has_pending_exception) {
+MaybeHandle<Object> Execution::TryGetConstructorDelegate(
+ Isolate* isolate, Handle<Object> object) {
ASSERT(!object->IsJSFunction());
// If you return a function from here, it will be called when an
@@ -316,38 +305,29 @@
// throw a non-callable exception.
i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError(
"called_non_callable", i::HandleVector<i::Object>(&object, 1));
- isolate->Throw(*error_obj);
- *has_pending_exception = true;
-
- return isolate->factory()->undefined_value();
+ return isolate->Throw<Object>(error_obj);
}
void Execution::RunMicrotasks(Isolate* isolate) {
ASSERT(isolate->microtask_pending());
- bool threw = false;
Execution::Call(
isolate,
isolate->run_microtasks(),
isolate->factory()->undefined_value(),
0,
- NULL,
- &threw);
- ASSERT(!threw);
+ NULL).Assert();
}
void Execution::EnqueueMicrotask(Isolate* isolate, Handle<Object> microtask) {
- bool threw = false;
Handle<Object> args[] = { microtask };
Execution::Call(
isolate,
isolate->enqueue_external_microtask(),
isolate->factory()->undefined_value(),
1,
- args,
- &threw);
- ASSERT(!threw);
+ args).Assert();
}
@@ -665,78 +645,78 @@
// --- C a l l s t o n a t i v e s ---
-#define RETURN_NATIVE_CALL(name, args, has_pending_exception) \
+#define RETURN_NATIVE_CALL(name, args) \
do { \
Handle<Object> argv[] = args; \
- ASSERT(has_pending_exception != NULL); \
return Call(isolate, \
isolate->name##_fun(), \
isolate->js_builtins_object(), \
- ARRAY_SIZE(argv), argv, \
- has_pending_exception); \
+ ARRAY_SIZE(argv), argv); \
} while (false)
-Handle<Object> Execution::ToNumber(
- Isolate* isolate, Handle<Object> obj, bool* exc) {
- RETURN_NATIVE_CALL(to_number, { obj }, exc);
+MaybeHandle<Object> Execution::ToNumber(
+ Isolate* isolate, Handle<Object> obj) {
+ RETURN_NATIVE_CALL(to_number, { obj });
}
-Handle<Object> Execution::ToString(
- Isolate* isolate, Handle<Object> obj, bool* exc) {
- RETURN_NATIVE_CALL(to_string, { obj }, exc);
+MaybeHandle<Object> Execution::ToString(
+ Isolate* isolate, Handle<Object> obj) {
+ RETURN_NATIVE_CALL(to_string, { obj });
}
-Handle<Object> Execution::ToDetailString(
- Isolate* isolate, Handle<Object> obj, bool* exc) {
- RETURN_NATIVE_CALL(to_detail_string, { obj }, exc);
+MaybeHandle<Object> Execution::ToDetailString(
+ Isolate* isolate, Handle<Object> obj) {
+ RETURN_NATIVE_CALL(to_detail_string, { obj });
}
-Handle<Object> Execution::ToObject(
- Isolate* isolate, Handle<Object> obj, bool* exc) {
+MaybeHandle<Object> Execution::ToObject(
+ Isolate* isolate, Handle<Object> obj) {
if (obj->IsSpecObject()) return obj;
- RETURN_NATIVE_CALL(to_object, { obj }, exc);
+ RETURN_NATIVE_CALL(to_object, { obj });
}
-Handle<Object> Execution::ToInteger(
- Isolate* isolate, Handle<Object> obj, bool* exc) {
- RETURN_NATIVE_CALL(to_integer, { obj }, exc);
+MaybeHandle<Object> Execution::ToInteger(
+ Isolate* isolate, Handle<Object> obj) {
+ RETURN_NATIVE_CALL(to_integer, { obj });
}
-Handle<Object> Execution::ToUint32(
- Isolate* isolate, Handle<Object> obj, bool* exc) {
- RETURN_NATIVE_CALL(to_uint32, { obj }, exc);
+MaybeHandle<Object> Execution::ToUint32(
+ Isolate* isolate, Handle<Object> obj) {
+ RETURN_NATIVE_CALL(to_uint32, { obj });
}
-Handle<Object> Execution::ToInt32(
- Isolate* isolate, Handle<Object> obj, bool* exc) {
- RETURN_NATIVE_CALL(to_int32, { obj }, exc);
+MaybeHandle<Object> Execution::ToInt32(
+ Isolate* isolate, Handle<Object> obj) {
+ RETURN_NATIVE_CALL(to_int32, { obj });
}
-Handle<Object> Execution::NewDate(Isolate* isolate, double time, bool* exc) {
+MaybeHandle<Object> Execution::NewDate(Isolate* isolate, double time) {
Handle<Object> time_obj = isolate->factory()->NewNumber(time);
- RETURN_NATIVE_CALL(create_date, { time_obj }, exc);
+ RETURN_NATIVE_CALL(create_date, { time_obj });
}
#undef RETURN_NATIVE_CALL
-Handle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
- Handle<String> flags,
- bool* exc) {
+MaybeHandle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern,
+ Handle<String> flags) {
+ Isolate* isolate = pattern->GetIsolate();
Handle<JSFunction> function = Handle<JSFunction>(
- pattern->GetIsolate()->native_context()->regexp_function());
- Handle<Object> re_obj = RegExpImpl::CreateRegExpLiteral(
- function, pattern, flags, exc);
- if (*exc) return Handle<JSRegExp>();
+ isolate->native_context()->regexp_function());
+ Handle<Object> re_obj;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, re_obj,
+ RegExpImpl::CreateRegExpLiteral(function, pattern, flags),
+ JSRegExp);
return Handle<JSRegExp>::cast(re_obj);
}
@@ -751,96 +731,90 @@
}
Handle<Object> char_at = Object::GetProperty(
- isolate->js_builtins_object(), factory->char_at_string());
+ isolate->js_builtins_object(),
+ factory->char_at_string()).ToHandleChecked();
if (!char_at->IsJSFunction()) {
return factory->undefined_value();
}
- bool caught_exception;
Handle<Object> index_object = factory->NewNumberFromInt(int_index);
Handle<Object> index_arg[] = { index_object };
- Handle<Object> result = TryCall(Handle<JSFunction>::cast(char_at),
- string,
- ARRAY_SIZE(index_arg),
- index_arg,
- &caught_exception);
- if (caught_exception) {
- return factory->undefined_value();
- }
+ Handle<Object> result;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate, result,
+ TryCall(Handle<JSFunction>::cast(char_at),
+ string,
+ ARRAY_SIZE(index_arg),
+ index_arg),
+ factory->undefined_value());
return result;
}
-Handle<JSFunction> Execution::InstantiateFunction(
- Handle<FunctionTemplateInfo> data,
- bool* exc) {
+MaybeHandle<JSFunction> Execution::InstantiateFunction(
+ Handle<FunctionTemplateInfo> data) {
Isolate* isolate = data->GetIsolate();
if (!data->do_not_cache()) {
// Fast case: see if the function has already been instantiated
int serial_number = Smi::cast(data->serial_number())->value();
Handle<JSObject> cache(isolate->native_context()->function_cache());
Handle<Object> elm =
- Object::GetElementNoExceptionThrown(isolate, cache, serial_number);
+ Object::GetElement(isolate, cache, serial_number).ToHandleChecked();
if (elm->IsJSFunction()) return Handle<JSFunction>::cast(elm);
}
// The function has not yet been instantiated in this context; do it.
Handle<Object> args[] = { data };
- Handle<Object> result = Call(isolate,
- isolate->instantiate_fun(),
- isolate->js_builtins_object(),
- ARRAY_SIZE(args),
- args,
- exc);
- if (*exc) return Handle<JSFunction>::null();
+ Handle<Object> result;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, result,
+ Call(isolate,
+ isolate->instantiate_fun(),
+ isolate->js_builtins_object(),
+ ARRAY_SIZE(args),
+ args),
+ JSFunction);
return Handle<JSFunction>::cast(result);
}
-Handle<JSObject> Execution::InstantiateObject(Handle<ObjectTemplateInfo> data,
- bool* exc) {
+MaybeHandle<JSObject> Execution::InstantiateObject(
+ Handle<ObjectTemplateInfo> data) {
Isolate* isolate = data->GetIsolate();
+ Handle<Object> result;
if (data->property_list()->IsUndefined() &&
!data->constructor()->IsUndefined()) {
- // Initialization to make gcc happy.
- Object* result = NULL;
- {
- HandleScope scope(isolate);
- Handle<FunctionTemplateInfo> cons_template =
- Handle<FunctionTemplateInfo>(
- FunctionTemplateInfo::cast(data->constructor()));
- Handle<JSFunction> cons = InstantiateFunction(cons_template, exc);
- if (*exc) return Handle<JSObject>::null();
- Handle<Object> value = New(cons, 0, NULL, exc);
- if (*exc) return Handle<JSObject>::null();
- result = *value;
- }
- ASSERT(!*exc);
- return Handle<JSObject>(JSObject::cast(result));
+ Handle<FunctionTemplateInfo> cons_template =
+ Handle<FunctionTemplateInfo>(
+ FunctionTemplateInfo::cast(data->constructor()));
+ Handle<JSFunction> cons;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, cons, InstantiateFunction(cons_template), JSObject);
+ ASSIGN_RETURN_ON_EXCEPTION(isolate, result, New(cons, 0, NULL), JSObject);
} else {
Handle<Object> args[] = { data };
- Handle<Object> result = Call(isolate,
- isolate->instantiate_fun(),
- isolate->js_builtins_object(),
- ARRAY_SIZE(args),
- args,
- exc);
- if (*exc) return Handle<JSObject>::null();
- return Handle<JSObject>::cast(result);
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, result,
+ Call(isolate,
+ isolate->instantiate_fun(),
+ isolate->js_builtins_object(),
+ ARRAY_SIZE(args),
+ args),
+ JSObject);
}
+ return Handle<JSObject>::cast(result);
}
-void Execution::ConfigureInstance(Isolate* isolate,
- Handle<Object> instance,
- Handle<Object> instance_template,
- bool* exc) {
+MaybeHandle<Object> Execution::ConfigureInstance(
+ Isolate* isolate,
+ Handle<Object> instance,
+ Handle<Object> instance_template) {
Handle<Object> args[] = { instance, instance_template };
- Execution::Call(isolate,
- isolate->configure_instance_fun(),
- isolate->js_builtins_object(),
- ARRAY_SIZE(args),
- args,
- exc);
+ return Execution::Call(isolate,
+ isolate->configure_instance_fun(),
+ isolate->js_builtins_object(),
+ ARRAY_SIZE(args),
+ args);
}
@@ -850,14 +824,14 @@
Handle<Object> is_global) {
Isolate* isolate = fun->GetIsolate();
Handle<Object> args[] = { recv, fun, pos, is_global };
- bool caught_exception;
- Handle<Object> result = TryCall(isolate->get_stack_trace_line_fun(),
- isolate->js_builtins_object(),
- ARRAY_SIZE(args),
- args,
- &caught_exception);
- if (caught_exception || !result->IsString()) {
- return isolate->factory()->empty_string();
+ MaybeHandle<Object> maybe_result =
+ TryCall(isolate->get_stack_trace_line_fun(),
+ isolate->js_builtins_object(),
+ ARRAY_SIZE(args),
+ args);
+ Handle<Object> result;
+ if (!maybe_result.ToHandle(&result) || !result->IsString()) {
+ return isolate->factory()->empty_string();
}
return Handle<String>::cast(result);
diff --git a/src/execution.h b/src/execution.h
index f328cae..4510fd1 100644
--- a/src/execution.h
+++ b/src/execution.h
@@ -38,13 +38,13 @@
// and the function called is not in strict mode, receiver is converted to
// an object.
//
- static Handle<Object> Call(Isolate* isolate,
- Handle<Object> callable,
- Handle<Object> receiver,
- int argc,
- Handle<Object> argv[],
- bool* pending_exception,
- bool convert_receiver = false);
+ MUST_USE_RESULT static MaybeHandle<Object> Call(
+ Isolate* isolate,
+ Handle<Object> callable,
+ Handle<Object> receiver,
+ int argc,
+ Handle<Object> argv[],
+ bool convert_receiver = false);
// Construct object from function, the caller supplies an array of
// arguments. Arguments are Object* type. After function returns,
@@ -53,70 +53,67 @@
// *pending_exception tells whether the invoke resulted in
// a pending exception.
//
- static Handle<Object> New(Handle<JSFunction> func,
- int argc,
- Handle<Object> argv[],
- bool* pending_exception);
+ MUST_USE_RESULT static MaybeHandle<Object> New(Handle<JSFunction> func,
+ int argc,
+ Handle<Object> argv[]);
// Call a function, just like Call(), but make sure to silently catch
// any thrown exceptions. The return value is either the result of
// calling the function (if caught exception is false) or the exception
// that occurred (if caught exception is true).
- static Handle<Object> TryCall(Handle<JSFunction> func,
- Handle<Object> receiver,
- int argc,
- Handle<Object> argv[],
- bool* caught_exception);
+ static MaybeHandle<Object> TryCall(
+ Handle<JSFunction> func,
+ Handle<Object> receiver,
+ int argc,
+ Handle<Object> argv[],
+ Handle<Object>* exception_out = NULL);
// ECMA-262 9.3
- static Handle<Object> ToNumber(
- Isolate* isolate, Handle<Object> obj, bool* exc);
+ MUST_USE_RESULT static MaybeHandle<Object> ToNumber(
+ Isolate* isolate, Handle<Object> obj);
// ECMA-262 9.4
- static Handle<Object> ToInteger(
- Isolate* isolate, Handle<Object> obj, bool* exc);
+ MUST_USE_RESULT static MaybeHandle<Object> ToInteger(
+ Isolate* isolate, Handle<Object> obj);
// ECMA-262 9.5
- static Handle<Object> ToInt32(
- Isolate* isolate, Handle<Object> obj, bool* exc);
+ MUST_USE_RESULT static MaybeHandle<Object> ToInt32(
+ Isolate* isolate, Handle<Object> obj);
// ECMA-262 9.6
- static Handle<Object> ToUint32(
- Isolate* isolate, Handle<Object> obj, bool* exc);
+ MUST_USE_RESULT static MaybeHandle<Object> ToUint32(
+ Isolate* isolate, Handle<Object> obj);
// ECMA-262 9.8
- static Handle<Object> ToString(
- Isolate* isolate, Handle<Object> obj, bool* exc);
+ MUST_USE_RESULT static MaybeHandle<Object> ToString(
+ Isolate* isolate, Handle<Object> obj);
// ECMA-262 9.8
- static Handle<Object> ToDetailString(
- Isolate* isolate, Handle<Object> obj, bool* exc);
+ MUST_USE_RESULT static MaybeHandle<Object> ToDetailString(
+ Isolate* isolate, Handle<Object> obj);
// ECMA-262 9.9
- static Handle<Object> ToObject(
- Isolate* isolate, Handle<Object> obj, bool* exc);
+ MUST_USE_RESULT static MaybeHandle<Object> ToObject(
+ Isolate* isolate, Handle<Object> obj);
// Create a new date object from 'time'.
- static Handle<Object> NewDate(
- Isolate* isolate, double time, bool* exc);
+ MUST_USE_RESULT static MaybeHandle<Object> NewDate(
+ Isolate* isolate, double time);
// Create a new regular expression object from 'pattern' and 'flags'.
- static Handle<JSRegExp> NewJSRegExp(Handle<String> pattern,
- Handle<String> flags,
- bool* exc);
+ MUST_USE_RESULT static MaybeHandle<JSRegExp> NewJSRegExp(
+ Handle<String> pattern, Handle<String> flags);
// Used to implement [] notation on strings (calls JS code)
static Handle<Object> CharAt(Handle<String> str, uint32_t index);
static Handle<Object> GetFunctionFor();
- static Handle<JSFunction> InstantiateFunction(
- Handle<FunctionTemplateInfo> data, bool* exc);
- static Handle<JSObject> InstantiateObject(Handle<ObjectTemplateInfo> data,
- bool* exc);
- static void ConfigureInstance(Isolate* isolate,
- Handle<Object> instance,
- Handle<Object> data,
- bool* exc);
+ MUST_USE_RESULT static MaybeHandle<JSFunction> InstantiateFunction(
+ Handle<FunctionTemplateInfo> data);
+ MUST_USE_RESULT static MaybeHandle<JSObject> InstantiateObject(
+ Handle<ObjectTemplateInfo> data);
+ MUST_USE_RESULT static MaybeHandle<Object> ConfigureInstance(
+ Isolate* isolate, Handle<Object> instance, Handle<Object> data);
static Handle<String> GetStackTraceLine(Handle<Object> recv,
Handle<JSFunction> fun,
Handle<Object> pos,
@@ -135,17 +132,16 @@
// object. Used for support calling objects as functions.
static Handle<Object> GetFunctionDelegate(Isolate* isolate,
Handle<Object> object);
- static Handle<Object> TryGetFunctionDelegate(Isolate* isolate,
- Handle<Object> object,
- bool* has_pending_exception);
+ MUST_USE_RESULT static MaybeHandle<Object> TryGetFunctionDelegate(
+ Isolate* isolate,
+ Handle<Object> object);
// Get a function delegate (or undefined) for the given non-function
// object. Used for support calling objects as constructors.
static Handle<Object> GetConstructorDelegate(Isolate* isolate,
Handle<Object> object);
- static Handle<Object> TryGetConstructorDelegate(Isolate* isolate,
- Handle<Object> object,
- bool* has_pending_exception);
+ static MaybeHandle<Object> TryGetConstructorDelegate(Isolate* isolate,
+ Handle<Object> object);
static void RunMicrotasks(Isolate* isolate);
static void EnqueueMicrotask(Isolate* isolate, Handle<Object> microtask);
diff --git a/src/factory.cc b/src/factory.cc
index 053f870..fc49e32 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -133,33 +133,6 @@
}
-Handle<DescriptorArray> Factory::NewDescriptorArray(int number_of_descriptors,
- int slack) {
- ASSERT(0 <= number_of_descriptors);
- CALL_HEAP_FUNCTION(isolate(),
- DescriptorArray::Allocate(
- isolate(), number_of_descriptors, slack),
- DescriptorArray);
-}
-
-
-Handle<TransitionArray> Factory::NewTransitionArray(int number_of_transitions) {
- ASSERT(0 <= number_of_transitions);
- CALL_HEAP_FUNCTION(isolate(),
- TransitionArray::Allocate(
- isolate(), number_of_transitions),
- TransitionArray);
-}
-
-
-Handle<TransitionArray> Factory::NewSimpleTransitionArray(Handle<Map> target) {
- CALL_HEAP_FUNCTION(isolate(),
- TransitionArray::AllocateSimple(
- isolate(), *target),
- TransitionArray);
-}
-
-
Handle<DeoptimizationInputData> Factory::NewDeoptimizationInputData(
int deopt_entry_count,
PretenureFlag pretenure) {
@@ -1122,7 +1095,7 @@
space--;
if (space > 0) {
Handle<String> arg_str = Handle<String>::cast(
- Object::GetElementNoExceptionThrown(isolate(), args, i));
+ Object::GetElement(isolate(), args, i).ToHandleChecked());
SmartArrayPointer<char> arg = arg_str->ToCString();
Vector<char> v2(p, static_cast<int>(space));
OS::StrNCpy(v2, arg.get(), space);
@@ -1145,8 +1118,8 @@
const char* message,
Handle<JSArray> args) {
Handle<String> make_str = InternalizeUtf8String(maker);
- Handle<Object> fun_obj = GlobalObject::GetPropertyNoExceptionThrown(
- isolate()->js_builtins_object(), make_str);
+ Handle<Object> fun_obj = Object::GetProperty(
+ isolate()->js_builtins_object(), make_str).ToHandleChecked();
// If the builtins haven't been properly configured yet this error
// constructor may not have been defined. Bail out.
if (!fun_obj->IsJSFunction()) {
@@ -1158,12 +1131,15 @@
// Invoke the JavaScript factory method. If an exception is thrown while
// running the factory method, use the exception as the result.
- bool caught_exception;
- Handle<Object> result = Execution::TryCall(fun,
- isolate()->js_builtins_object(),
- ARRAY_SIZE(argv),
- argv,
- &caught_exception);
+ Handle<Object> result;
+ Handle<Object> exception;
+ if (!Execution::TryCall(fun,
+ isolate()->js_builtins_object(),
+ ARRAY_SIZE(argv),
+ argv,
+ &exception).ToHandle(&result)) {
+ return exception;
+ }
return result;
}
@@ -1176,19 +1152,21 @@
Handle<Object> Factory::NewError(const char* constructor,
Handle<String> message) {
Handle<String> constr = InternalizeUtf8String(constructor);
- Handle<JSFunction> fun = Handle<JSFunction>::cast(
- GlobalObject::GetPropertyNoExceptionThrown(
- isolate()->js_builtins_object(), constr));
+ Handle<JSFunction> fun = Handle<JSFunction>::cast(Object::GetProperty(
+ isolate()->js_builtins_object(), constr).ToHandleChecked());
Handle<Object> argv[] = { message };
// Invoke the JavaScript factory method. If an exception is thrown while
// running the factory method, use the exception as the result.
- bool caught_exception;
- Handle<Object> result = Execution::TryCall(fun,
- isolate()->js_builtins_object(),
- ARRAY_SIZE(argv),
- argv,
- &caught_exception);
+ Handle<Object> result;
+ Handle<Object> exception;
+ if (!Execution::TryCall(fun,
+ isolate()->js_builtins_object(),
+ ARRAY_SIZE(argv),
+ argv,
+ &exception).ToHandle(&result)) {
+ return exception;
+ }
return result;
}
@@ -1991,28 +1969,25 @@
-void Factory::ConfigureInstance(Handle<FunctionTemplateInfo> desc,
- Handle<JSObject> instance,
- bool* pending_exception) {
+MaybeHandle<FunctionTemplateInfo> Factory::ConfigureInstance(
+ Handle<FunctionTemplateInfo> desc, Handle<JSObject> instance) {
// Configure the instance by adding the properties specified by the
// instance template.
Handle<Object> instance_template(desc->instance_template(), isolate());
if (!instance_template->IsUndefined()) {
- Execution::ConfigureInstance(isolate(),
- instance,
- instance_template,
- pending_exception);
- } else {
- *pending_exception = false;
+ RETURN_ON_EXCEPTION(
+ isolate(),
+ Execution::ConfigureInstance(isolate(), instance, instance_template),
+ FunctionTemplateInfo);
}
+ return desc;
}
Handle<Object> Factory::GlobalConstantFor(Handle<String> name) {
- Heap* h = isolate()->heap();
- if (name->Equals(h->undefined_string())) return undefined_value();
- if (name->Equals(h->nan_string())) return nan_value();
- if (name->Equals(h->infinity_string())) return infinity_value();
+ if (String::Equals(name, undefined_string())) return undefined_value();
+ if (String::Equals(name, nan_string())) return nan_value();
+ if (String::Equals(name, infinity_string())) return infinity_value();
return Handle<Object>::null();
}
diff --git a/src/factory.h b/src/factory.h
index c94a126..ae861ba 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -55,10 +55,6 @@
Handle<WeakHashTable> NewWeakHashTable(int at_least_space_for);
- Handle<DescriptorArray> NewDescriptorArray(int number_of_descriptors,
- int slack = 0);
- Handle<TransitionArray> NewTransitionArray(int number_of_transitions);
- Handle<TransitionArray> NewSimpleTransitionArray(Handle<Map> target);
Handle<DeoptimizationInputData> NewDeoptimizationInputData(
int deopt_entry_count,
PretenureFlag pretenure);
@@ -507,9 +503,8 @@
// Installs interceptors on the instance. 'desc' is a function template,
// and instance is an object instance created by the function of this
// function template.
- void ConfigureInstance(Handle<FunctionTemplateInfo> desc,
- Handle<JSObject> instance,
- bool* pending_exception);
+ MUST_USE_RESULT MaybeHandle<FunctionTemplateInfo> ConfigureInstance(
+ Handle<FunctionTemplateInfo> desc, Handle<JSObject> instance);
#define ROOT_ACCESSOR(type, name, camel_name) \
inline Handle<type> name() { \
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 0cb3f90..1942c35 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -515,6 +515,8 @@
"it is adjusted.")
DEFINE_bool(collect_maps, true,
"garbage collect maps from which no objects can be reached")
+DEFINE_bool(weak_embedded_maps_in_ic, true,
+ "make maps embedded in inline cache stubs")
DEFINE_bool(weak_embedded_maps_in_optimized_code, true,
"make maps embedded in optimized code weak")
DEFINE_bool(weak_embedded_objects_in_optimized_code, true,
diff --git a/src/func-name-inferrer.cc b/src/func-name-inferrer.cc
index e85e895..51ba4ad 100644
--- a/src/func-name-inferrer.cc
+++ b/src/func-name-inferrer.cc
@@ -55,14 +55,16 @@
void FuncNameInferrer::PushLiteralName(Handle<String> name) {
- if (IsOpen() && !isolate()->heap()->prototype_string()->Equals(*name)) {
+ if (IsOpen() &&
+ !String::Equals(isolate()->factory()->prototype_string(), name)) {
names_stack_.Add(Name(name, kLiteralName), zone());
}
}
void FuncNameInferrer::PushVariableName(Handle<String> name) {
- if (IsOpen() && !isolate()->heap()->dot_result_string()->Equals(*name)) {
+ if (IsOpen() &&
+ !String::Equals(isolate()->factory()->dot_result_string(), name)) {
names_stack_.Add(Name(name, kVariableName), zone());
}
}
diff --git a/src/handles.cc b/src/handles.cc
index 0c6cbd3..af1ffab 100644
--- a/src/handles.cc
+++ b/src/handles.cc
@@ -175,14 +175,6 @@
Handle<JSValue> result =
Handle<JSValue>::cast(isolate->factory()->NewJSObject(constructor));
- // The allocation might have triggered a GC, which could have called this
- // function recursively, and a wrapper has already been created and cached.
- // In that case, simply return a handle for the cached wrapper.
- if (script->wrapper()->foreign_address() != NULL) {
- return Handle<JSValue>(
- *reinterpret_cast<JSValue**>(script->wrapper()->foreign_address()));
- }
-
result->set_value(*script);
// Create a new weak global handle and use it to cache the wrapper
@@ -402,16 +394,15 @@
isolate->factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR("nameOrSourceURL"));
Handle<JSValue> script_wrapper = GetScriptWrapper(script);
- Handle<Object> property =
- Object::GetProperty(script_wrapper, name_or_source_url_key);
+ Handle<Object> property = Object::GetProperty(
+ script_wrapper, name_or_source_url_key).ToHandleChecked();
ASSERT(property->IsJSFunction());
Handle<JSFunction> method = Handle<JSFunction>::cast(property);
- bool caught_exception;
- Handle<Object> result = Execution::TryCall(method, script_wrapper, 0,
- NULL, &caught_exception);
- if (caught_exception) {
- result = isolate->factory()->undefined_value();
- }
+ Handle<Object> result;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate, result,
+ Execution::TryCall(method, script_wrapper, 0, NULL),
+ isolate->factory()->undefined_value());
return result;
}
@@ -445,17 +436,19 @@
if (p->IsJSProxy()) {
Handle<JSProxy> proxy(JSProxy::cast(*p), isolate);
Handle<Object> args[] = { proxy };
- bool has_pending_exception;
- Handle<Object> names = Execution::Call(isolate,
- isolate->proxy_enumerate(),
- object,
- ARRAY_SIZE(args),
- args,
- &has_pending_exception);
- if (has_pending_exception) return MaybeHandle<FixedArray>();
+ Handle<Object> names;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, names,
+ Execution::Call(isolate,
+ isolate->proxy_enumerate(),
+ object,
+ ARRAY_SIZE(args),
+ args),
+ FixedArray);
ASSIGN_RETURN_ON_EXCEPTION(
isolate, content,
- FixedArray::AddKeysFromJSArray(content, Handle<JSArray>::cast(names)),
+ FixedArray::AddKeysFromJSArray(
+ content, Handle<JSArray>::cast(names)),
FixedArray);
break;
}
@@ -536,25 +529,12 @@
// If we only want local properties we bail out after the first
// iteration.
- if (type == LOCAL_ONLY)
- break;
+ if (type == LOCAL_ONLY) break;
}
return content;
}
-MaybeHandle<JSArray> GetKeysFor(Handle<JSReceiver> object) {
- Isolate* isolate = object->GetIsolate();
- isolate->counters()->for_in()->Increment();
- Handle<FixedArray> elements;
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, elements,
- GetKeysInFixedArrayFor(object, INCLUDE_PROTOS),
- JSArray);
- return isolate->factory()->NewJSArrayWithElements(elements);
-}
-
-
Handle<FixedArray> ReduceFixedArrayTo(Handle<FixedArray> array, int length) {
ASSERT(array->length() >= length);
if (array->length() == length) return array;
@@ -714,7 +694,7 @@
Handle<Code> code) {
heap->EnsureWeakObjectToCodeTable();
Handle<DependentCode> dep(heap->LookupWeakObjectToCodeDependency(*object));
- dep = DependentCode::Insert(dep, DependentCode::kWeaklyEmbeddedGroup, code);
+ dep = DependentCode::Insert(dep, DependentCode::kWeakCodeGroup, code);
CALL_HEAP_FUNCTION_VOID(heap->isolate(),
heap->AddWeakObjectToCodeDependency(*object, *dep));
}
diff --git a/src/handles.h b/src/handles.h
index 1100f5b..b27394a 100644
--- a/src/handles.h
+++ b/src/handles.h
@@ -319,9 +319,7 @@
// Computes the enumerable keys for a JSObject. Used for implementing
// "for (n in object) { }".
MUST_USE_RESULT MaybeHandle<FixedArray> GetKeysInFixedArrayFor(
- Handle<JSReceiver> object,
- KeyCollectionType type);
-MUST_USE_RESULT MaybeHandle<JSArray> GetKeysFor(Handle<JSReceiver> object);
+ Handle<JSReceiver> object, KeyCollectionType type);
Handle<FixedArray> ReduceFixedArrayTo(Handle<FixedArray> array, int length);
Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object,
bool cache_result);
diff --git a/src/heap-inl.h b/src/heap-inl.h
index ea7dcda..8c94013 100644
--- a/src/heap-inl.h
+++ b/src/heap-inl.h
@@ -490,6 +490,41 @@
}
+AllocationMemento* Heap::FindAllocationMemento(HeapObject* object) {
+ // Check if there is potentially a memento behind the object. If
+ // the last word of the momento is on another page we return
+ // immediately.
+ Address object_address = object->address();
+ Address memento_address = object_address + object->Size();
+ Address last_memento_word_address = memento_address + kPointerSize;
+ if (!NewSpacePage::OnSamePage(object_address,
+ last_memento_word_address)) {
+ return NULL;
+ }
+
+ HeapObject* candidate = HeapObject::FromAddress(memento_address);
+ if (candidate->map() != allocation_memento_map()) return NULL;
+
+ // Either the 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. Note that technically we do not have
+ // to compare with the current top pointer of the from space page during GC,
+ // since we always install filler objects above the top pointer of a from
+ // space page when performing a garbage collection. However, always performing
+ // the test makes it possible to have a single, unified version of
+ // FindAllocationMemento that is used both by the GC and the mutator.
+ Address top = NewSpaceTop();
+ ASSERT(memento_address == top ||
+ memento_address + HeapObject::kHeaderSize <= top ||
+ !NewSpacePage::OnSamePage(memento_address, top));
+ if (memento_address == top) return NULL;
+
+ AllocationMemento* memento = AllocationMemento::cast(candidate);
+ if (!memento->IsValid()) return NULL;
+ return memento;
+}
+
+
void Heap::UpdateAllocationSiteFeedback(HeapObject* object,
ScratchpadSlotMode mode) {
Heap* heap = object->GetHeap();
@@ -498,25 +533,8 @@
if (!FLAG_allocation_site_pretenuring ||
!AllocationSite::CanTrack(object->map()->instance_type())) return;
- // Check if there is potentially a memento behind the object. If
- // the last word of the momento is on another page we return
- // immediatelly. Note that we do not have to compare with the current
- // top pointer of the from space page, since we always install filler
- // objects above the top pointer of a from space page when performing
- // a garbage collection.
- Address object_address = object->address();
- Address memento_address = object_address + object->Size();
- Address last_memento_word_address = memento_address + kPointerSize;
- if (!NewSpacePage::OnSamePage(object_address,
- last_memento_word_address)) {
- return;
- }
-
- HeapObject* candidate = HeapObject::FromAddress(memento_address);
- if (candidate->map() != heap->allocation_memento_map()) return;
-
- AllocationMemento* memento = AllocationMemento::cast(candidate);
- if (!memento->IsValid()) return;
+ AllocationMemento* memento = heap->FindAllocationMemento(object);
+ if (memento == NULL) return;
if (memento->GetAllocationSite()->IncrementMementoFoundCount()) {
heap->AddAllocationSiteToScratchpad(memento->GetAllocationSite(), mode);
@@ -560,25 +578,6 @@
}
-MaybeObject* Heap::PrepareForCompare(String* str) {
- // Always flatten small strings and force flattening of long strings
- // after we have accumulated a certain amount we failed to flatten.
- static const int kMaxAlwaysFlattenLength = 32;
- static const int kFlattenLongThreshold = 16*KB;
-
- const int length = str->length();
- MaybeObject* obj = str->TryFlatten();
- if (length <= kMaxAlwaysFlattenLength ||
- unflattened_strings_length_ >= kFlattenLongThreshold) {
- return obj;
- }
- if (obj->IsFailure()) {
- unflattened_strings_length_ += length;
- }
- return str;
-}
-
-
int64_t Heap::AdjustAmountOfExternalAllocatedMemory(
int64_t change_in_bytes) {
ASSERT(HasBeenSetUp());
diff --git a/src/heap.cc b/src/heap.cc
index 139a64d..00e513b 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -1710,180 +1710,6 @@
}
-template <class T>
-struct WeakListVisitor;
-
-
-template <class T>
-static Object* VisitWeakList(Heap* heap,
- Object* list,
- WeakObjectRetainer* retainer,
- bool record_slots) {
- Object* undefined = heap->undefined_value();
- Object* head = undefined;
- T* tail = NULL;
- MarkCompactCollector* collector = heap->mark_compact_collector();
- while (list != undefined) {
- // Check whether to keep the candidate in the list.
- T* candidate = reinterpret_cast<T*>(list);
- Object* retained = retainer->RetainAs(list);
- if (retained != NULL) {
- if (head == undefined) {
- // First element in the list.
- head = retained;
- } else {
- // Subsequent elements in the list.
- ASSERT(tail != NULL);
- WeakListVisitor<T>::SetWeakNext(tail, retained);
- if (record_slots) {
- Object** next_slot =
- HeapObject::RawField(tail, WeakListVisitor<T>::WeakNextOffset());
- collector->RecordSlot(next_slot, next_slot, retained);
- }
- }
- // Retained object is new tail.
- ASSERT(!retained->IsUndefined());
- candidate = reinterpret_cast<T*>(retained);
- tail = candidate;
-
-
- // tail is a live object, visit it.
- WeakListVisitor<T>::VisitLiveObject(
- heap, tail, retainer, record_slots);
- } else {
- WeakListVisitor<T>::VisitPhantomObject(heap, candidate);
- }
-
- // Move to next element in the list.
- list = WeakListVisitor<T>::WeakNext(candidate);
- }
-
- // Terminate the list if there is one or more elements.
- if (tail != NULL) {
- WeakListVisitor<T>::SetWeakNext(tail, undefined);
- }
- return head;
-}
-
-
-template <class T>
-static void ClearWeakList(Heap* heap,
- Object* list) {
- Object* undefined = heap->undefined_value();
- while (list != undefined) {
- T* candidate = reinterpret_cast<T*>(list);
- list = WeakListVisitor<T>::WeakNext(candidate);
- WeakListVisitor<T>::SetWeakNext(candidate, undefined);
- }
-}
-
-
-template<>
-struct WeakListVisitor<JSFunction> {
- static void SetWeakNext(JSFunction* function, Object* next) {
- function->set_next_function_link(next);
- }
-
- static Object* WeakNext(JSFunction* function) {
- return function->next_function_link();
- }
-
- static int WeakNextOffset() {
- return JSFunction::kNextFunctionLinkOffset;
- }
-
- static void VisitLiveObject(Heap*, JSFunction*,
- WeakObjectRetainer*, bool) {
- }
-
- static void VisitPhantomObject(Heap*, JSFunction*) {
- }
-};
-
-
-template<>
-struct WeakListVisitor<Code> {
- static void SetWeakNext(Code* code, Object* next) {
- code->set_next_code_link(next);
- }
-
- static Object* WeakNext(Code* code) {
- return code->next_code_link();
- }
-
- static int WeakNextOffset() {
- return Code::kNextCodeLinkOffset;
- }
-
- static void VisitLiveObject(Heap*, Code*,
- WeakObjectRetainer*, bool) {
- }
-
- static void VisitPhantomObject(Heap*, Code*) {
- }
-};
-
-
-template<>
-struct WeakListVisitor<Context> {
- static void SetWeakNext(Context* context, Object* next) {
- context->set(Context::NEXT_CONTEXT_LINK,
- next,
- UPDATE_WRITE_BARRIER);
- }
-
- static Object* WeakNext(Context* context) {
- return context->get(Context::NEXT_CONTEXT_LINK);
- }
-
- static void VisitLiveObject(Heap* heap,
- Context* context,
- WeakObjectRetainer* retainer,
- bool record_slots) {
- // Process the three weak lists linked off the context.
- DoWeakList<JSFunction>(heap, context, retainer, record_slots,
- Context::OPTIMIZED_FUNCTIONS_LIST);
- DoWeakList<Code>(heap, context, retainer, record_slots,
- Context::OPTIMIZED_CODE_LIST);
- DoWeakList<Code>(heap, context, retainer, record_slots,
- Context::DEOPTIMIZED_CODE_LIST);
- }
-
- template<class T>
- static void DoWeakList(Heap* heap,
- Context* context,
- WeakObjectRetainer* retainer,
- bool record_slots,
- int index) {
- // Visit the weak list, removing dead intermediate elements.
- Object* list_head = VisitWeakList<T>(heap, context->get(index), retainer,
- record_slots);
-
- // Update the list head.
- context->set(index, list_head, UPDATE_WRITE_BARRIER);
-
- if (record_slots) {
- // Record the updated slot if necessary.
- Object** head_slot = HeapObject::RawField(
- context, FixedArray::SizeFor(index));
- heap->mark_compact_collector()->RecordSlot(
- head_slot, head_slot, list_head);
- }
- }
-
- static void VisitPhantomObject(Heap* heap, Context* context) {
- ClearWeakList<JSFunction>(heap,
- context->get(Context::OPTIMIZED_FUNCTIONS_LIST));
- ClearWeakList<Code>(heap, context->get(Context::OPTIMIZED_CODE_LIST));
- ClearWeakList<Code>(heap, context->get(Context::DEOPTIMIZED_CODE_LIST));
- }
-
- static int WeakNextOffset() {
- return FixedArray::SizeFor(Context::NEXT_CONTEXT_LINK);
- }
-};
-
-
void Heap::ProcessWeakReferences(WeakObjectRetainer* retainer) {
// We don't record weak slots during marking or scavenges.
// Instead we do it once when we complete mark-compact cycle.
@@ -1909,66 +1735,6 @@
}
-template<>
-struct WeakListVisitor<JSArrayBufferView> {
- static void SetWeakNext(JSArrayBufferView* obj, Object* next) {
- obj->set_weak_next(next);
- }
-
- static Object* WeakNext(JSArrayBufferView* obj) {
- return obj->weak_next();
- }
-
- static void VisitLiveObject(Heap*,
- JSArrayBufferView* obj,
- WeakObjectRetainer* retainer,
- bool record_slots) {}
-
- static void VisitPhantomObject(Heap*, JSArrayBufferView*) {}
-
- static int WeakNextOffset() {
- return JSArrayBufferView::kWeakNextOffset;
- }
-};
-
-
-template<>
-struct WeakListVisitor<JSArrayBuffer> {
- static void SetWeakNext(JSArrayBuffer* obj, Object* next) {
- obj->set_weak_next(next);
- }
-
- static Object* WeakNext(JSArrayBuffer* obj) {
- return obj->weak_next();
- }
-
- static void VisitLiveObject(Heap* heap,
- JSArrayBuffer* array_buffer,
- WeakObjectRetainer* retainer,
- bool record_slots) {
- Object* typed_array_obj =
- VisitWeakList<JSArrayBufferView>(
- heap,
- array_buffer->weak_first_view(),
- retainer, record_slots);
- array_buffer->set_weak_first_view(typed_array_obj);
- if (typed_array_obj != heap->undefined_value() && record_slots) {
- Object** slot = HeapObject::RawField(
- array_buffer, JSArrayBuffer::kWeakFirstViewOffset);
- heap->mark_compact_collector()->RecordSlot(slot, slot, typed_array_obj);
- }
- }
-
- static void VisitPhantomObject(Heap* heap, JSArrayBuffer* phantom) {
- Runtime::FreeArrayBuffer(heap->isolate(), phantom);
- }
-
- static int WeakNextOffset() {
- return JSArrayBuffer::kWeakNextOffset;
- }
-};
-
-
void Heap::ProcessArrayBuffers(WeakObjectRetainer* retainer,
bool record_slots) {
Object* array_buffer_obj =
@@ -1990,29 +1756,6 @@
}
-template<>
-struct WeakListVisitor<AllocationSite> {
- static void SetWeakNext(AllocationSite* obj, Object* next) {
- obj->set_weak_next(next);
- }
-
- static Object* WeakNext(AllocationSite* obj) {
- return obj->weak_next();
- }
-
- static void VisitLiveObject(Heap* heap,
- AllocationSite* site,
- WeakObjectRetainer* retainer,
- bool record_slots) {}
-
- static void VisitPhantomObject(Heap* heap, AllocationSite* phantom) {}
-
- static int WeakNextOffset() {
- return AllocationSite::kWeakNextOffset;
- }
-};
-
-
void Heap::ProcessAllocationSites(WeakObjectRetainer* retainer,
bool record_slots) {
Object* allocation_site_obj =
@@ -4163,7 +3906,11 @@
code->set_ic_age(global_ic_age_);
code->set_prologue_offset(prologue_offset);
if (code->kind() == Code::OPTIMIZED_FUNCTION) {
- code->set_marked_for_deoptimization(false);
+ ASSERT(!code->marked_for_deoptimization());
+ }
+ if (code->is_inline_cache_stub()) {
+ ASSERT(!code->is_weak_stub());
+ ASSERT(!code->is_invalidated_weak_stub());
}
if (FLAG_enable_ool_constant_pool) {
diff --git a/src/heap.h b/src/heap.h
index 0f87fd1..1f7526e 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -1169,15 +1169,6 @@
// NULL is returned if string is in new space or not flattened.
Map* InternalizedStringMapForString(String* str);
- // Tries to flatten a string before compare operation.
- //
- // Returns a failure in case it was decided that flattening was
- // necessary and failed. Note, if flattening is not necessary the
- // string might stay non-flat even when not a failure is returned.
- //
- // Please note this function does not perform a garbage collection.
- MUST_USE_RESULT inline MaybeObject* PrepareForCompare(String* str);
-
// Converts the given boolean condition to JavaScript boolean value.
inline Object* ToBoolean(bool condition);
@@ -1461,6 +1452,10 @@
RECORD_SCRATCHPAD_SLOT
};
+ // If an object has an AllocationMemento trailing it, return it, otherwise
+ // return NULL;
+ inline AllocationMemento* FindAllocationMemento(HeapObject* object);
+
// An object may have an AllocationSite associated with it through a trailing
// AllocationMemento. Its feedback should be updated when objects are found
// in the heap.
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 4f728c6..336c9f7 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -509,6 +509,7 @@
!(block()->IsReachable() ||
IsBlockEntry() ||
IsControlInstruction() ||
+ IsArgumentsObject() ||
IsCapturedObject() ||
IsSimulate() ||
IsEnterInlined() ||
@@ -589,17 +590,6 @@
}
-void HValue::PrintRangeTo(StringStream* stream) {
- if (range() == NULL || range()->IsMostGeneric()) return;
- // Note: The c1visualizer syntax for locals allows only a sequence of the
- // following characters: A-Za-z0-9_-|:
- stream->Add(" range:%d_%d%s",
- range()->lower(),
- range()->upper(),
- range()->CanBeMinusZero() ? "_m0" : "");
-}
-
-
void HValue::PrintChangesTo(StringStream* stream) {
GVNFlagSet changes_flags = ChangesFlags();
if (changes_flags.IsEmpty()) return;
@@ -700,7 +690,6 @@
void HInstruction::PrintTo(StringStream* stream) {
PrintMnemonicTo(stream);
PrintDataTo(stream);
- PrintRangeTo(stream);
PrintChangesTo(stream);
PrintTypeTo(stream);
if (CheckFlag(HValue::kHasNoObservableSideEffects)) {
@@ -2498,7 +2487,6 @@
int32_non_phi_uses() + int32_indirect_uses(),
double_non_phi_uses() + double_indirect_uses(),
tagged_non_phi_uses() + tagged_indirect_uses());
- PrintRangeTo(stream);
PrintTypeTo(stream);
stream->Add("]");
}
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index e558ac7..26501d0 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -684,6 +684,9 @@
type_(type),
use_list_(NULL),
range_(NULL),
+#ifdef DEBUG
+ range_poisoned_(false),
+#endif
flags_(0) {}
virtual ~HValue() {}
@@ -854,9 +857,17 @@
return result;
}
- Range* range() const { return range_; }
- // TODO(svenpanne) We should really use the null object pattern here.
- bool HasRange() const { return range_ != NULL; }
+ Range* range() const {
+ ASSERT(!range_poisoned_);
+ return range_;
+ }
+ bool HasRange() const {
+ ASSERT(!range_poisoned_);
+ return range_ != NULL;
+ }
+#ifdef DEBUG
+ void PoisonRange() { range_poisoned_ = true; }
+#endif
void AddNewRange(Range* r, Zone* zone);
void RemoveLastAddedRange();
void ComputeInitialRange(Zone* zone);
@@ -888,7 +899,6 @@
virtual void PrintTo(StringStream* stream) = 0;
void PrintNameTo(StringStream* stream);
void PrintTypeTo(StringStream* stream);
- void PrintRangeTo(StringStream* stream);
void PrintChangesTo(StringStream* stream);
const char* Mnemonic() const;
@@ -1028,6 +1038,9 @@
HType type_;
HUseListNode* use_list_;
Range* range_;
+#ifdef DEBUG
+ bool range_poisoned_;
+#endif
int flags_;
GVNFlagSet changes_flags_;
GVNFlagSet depends_on_flags_;
diff --git a/src/hydrogen-range-analysis.cc b/src/hydrogen-range-analysis.cc
index 9d58fc8..6924a07 100644
--- a/src/hydrogen-range-analysis.cc
+++ b/src/hydrogen-range-analysis.cc
@@ -123,6 +123,22 @@
block = NULL;
}
}
+
+ // The ranges are not valid anymore due to SSI vs. SSA!
+ PoisonRanges();
+}
+
+
+void HRangeAnalysisPhase::PoisonRanges() {
+#ifdef DEBUG
+ for (int i = 0; i < graph()->blocks()->length(); ++i) {
+ HBasicBlock* block = graph()->blocks()->at(i);
+ for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
+ HInstruction* instr = it.Current();
+ if (instr->HasRange()) instr->PoisonRange();
+ }
+ }
+#endif
}
diff --git a/src/hydrogen-range-analysis.h b/src/hydrogen-range-analysis.h
index e0cc3c5..b474f69 100644
--- a/src/hydrogen-range-analysis.h
+++ b/src/hydrogen-range-analysis.h
@@ -57,6 +57,7 @@
worklist_.Add(value, zone());
}
void PropagateMinusZeroChecks(HValue* value);
+ void PoisonRanges();
ZoneList<HValue*> changed_ranges_;
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index a291a87..cf34517 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -5341,6 +5341,24 @@
HInstruction* HOptimizedGraphBuilder::BuildLoadNamedField(
PropertyAccessInfo* info,
HValue* checked_object) {
+ // See if this is a load for an immutable property
+ if (checked_object->ActualValue()->IsConstant() &&
+ info->lookup()->IsCacheable() &&
+ info->lookup()->IsReadOnly() && info->lookup()->IsDontDelete()) {
+ Handle<Object> object(
+ HConstant::cast(checked_object->ActualValue())->handle(isolate()));
+
+ if (object->IsJSObject()) {
+ LookupResult lookup(isolate());
+ Handle<JSObject>::cast(object)->Lookup(*info->name(), &lookup);
+ Handle<Object> value(lookup.GetLazyValue(), isolate());
+
+ if (!value->IsTheHole()) {
+ return New<HConstant>(value);
+ }
+ }
+ }
+
HObjectAccess access = info->access();
if (access.representation().IsDouble()) {
// Load the heap number.
@@ -9833,6 +9851,17 @@
if (combined_type->Is(Type::Receiver())) {
if (Token::IsEqualityOp(op)) {
+ // HCompareObjectEqAndBranch can only deal with object, so
+ // exclude numbers.
+ if ((left->IsConstant() &&
+ HConstant::cast(left)->HasNumberValue()) ||
+ (right->IsConstant() &&
+ HConstant::cast(right)->HasNumberValue())) {
+ Add<HDeoptimize>("Type mismatch between feedback and constant",
+ Deoptimizer::SOFT);
+ // The caller expects a branch instruction, so make it happy.
+ return New<HBranch>(graph()->GetConstantTrue());
+ }
// Can we get away with map check and not instance type check?
HValue* operand_to_check =
left->block()->block_id() < right->block()->block_id() ? left : right;
@@ -9879,17 +9908,6 @@
New<HCompareObjectEqAndBranch>(left, right);
return result;
} else if (combined_type->Is(Type::String())) {
- // If we have a constant argument, it should be consistent with the type
- // feedback (otherwise we fail assertions in HCompareObjectEqAndBranch).
- if ((left->IsConstant() &&
- !HConstant::cast(left)->HasStringValue()) ||
- (right->IsConstant() &&
- !HConstant::cast(right)->HasStringValue())) {
- Add<HDeoptimize>("Type mismatch between feedback and constant",
- Deoptimizer::SOFT);
- // The caller expects a branch instruction, so make it happy.
- return New<HBranch>(graph()->GetConstantTrue());
- }
BuildCheckHeapObject(left);
Add<HCheckInstanceType>(left, HCheckInstanceType::IS_STRING);
BuildCheckHeapObject(right);
diff --git a/src/hydrogen.h b/src/hydrogen.h
index 6d81307..ac6b99d 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -2393,10 +2393,10 @@
int offset;
if (Accessors::IsJSObjectFieldAccessor<Type>(type_, name_, &offset)) {
if (type_->Is(Type::String())) {
- ASSERT(name_->Equals(isolate()->heap()->length_string()));
+ ASSERT(String::Equals(isolate()->factory()->length_string(), name_));
*access = HObjectAccess::ForStringLength();
} else if (type_->Is(Type::Array())) {
- ASSERT(name_->Equals(isolate()->heap()->length_string()));
+ ASSERT(String::Equals(isolate()->factory()->length_string(), name_));
*access = HObjectAccess::ForArrayLength(map()->elements_kind());
} else {
*access = HObjectAccess::ForMapAndOffset(map(), offset);
diff --git a/src/i18n.cc b/src/i18n.cc
index 910414f..bfe4200 100644
--- a/src/i18n.cc
+++ b/src/i18n.cc
@@ -58,7 +58,7 @@
const char* key,
icu::UnicodeString* setting) {
Handle<String> str = isolate->factory()->NewStringFromAscii(CStrVector(key));
- Handle<Object> object = Object::GetProperty(options, str);
+ Handle<Object> object = Object::GetProperty(options, str).ToHandleChecked();
if (object->IsString()) {
v8::String::Utf8Value utf8_string(
v8::Utils::ToLocal(Handle<String>::cast(object)));
@@ -74,7 +74,7 @@
const char* key,
int32_t* value) {
Handle<String> str = isolate->factory()->NewStringFromAscii(CStrVector(key));
- Handle<Object> object = Object::GetProperty(options, str);
+ Handle<Object> object = Object::GetProperty(options, str).ToHandleChecked();
if (object->IsNumber()) {
object->ToInt32(value);
return true;
@@ -88,7 +88,7 @@
const char* key,
bool* value) {
Handle<String> str = isolate->factory()->NewStringFromAscii(CStrVector(key));
- Handle<Object> object = Object::GetProperty(options, str);
+ Handle<Object> object = Object::GetProperty(options, str).ToHandleChecked();
if (object->IsBoolean()) {
*value = object->BooleanValue();
return true;
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index b021e46..5622c30 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -4536,12 +4536,13 @@
}
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
- if (check->Equals(isolate()->heap()->number_string())) {
+ Factory* factory = isolate()->factory();
+ if (String::Equals(check, factory->number_string())) {
__ JumpIfSmi(eax, if_true);
__ cmp(FieldOperand(eax, HeapObject::kMapOffset),
isolate()->factory()->heap_number_map());
Split(equal, if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->string_string())) {
+ } else if (String::Equals(check, factory->string_string())) {
__ JumpIfSmi(eax, if_false);
__ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx);
__ j(above_equal, if_false);
@@ -4549,20 +4550,20 @@
__ test_b(FieldOperand(edx, Map::kBitFieldOffset),
1 << Map::kIsUndetectable);
Split(zero, if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->symbol_string())) {
+ } else if (String::Equals(check, factory->symbol_string())) {
__ JumpIfSmi(eax, if_false);
__ CmpObjectType(eax, SYMBOL_TYPE, edx);
Split(equal, if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->boolean_string())) {
+ } else if (String::Equals(check, factory->boolean_string())) {
__ cmp(eax, isolate()->factory()->true_value());
__ j(equal, if_true);
__ cmp(eax, isolate()->factory()->false_value());
Split(equal, if_true, if_false, fall_through);
} else if (FLAG_harmony_typeof &&
- check->Equals(isolate()->heap()->null_string())) {
+ String::Equals(check, factory->null_string())) {
__ cmp(eax, isolate()->factory()->null_value());
Split(equal, if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->undefined_string())) {
+ } else if (String::Equals(check, factory->undefined_string())) {
__ cmp(eax, isolate()->factory()->undefined_value());
__ j(equal, if_true);
__ JumpIfSmi(eax, if_false);
@@ -4571,14 +4572,14 @@
__ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
__ test(ecx, Immediate(1 << Map::kIsUndetectable));
Split(not_zero, if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->function_string())) {
+ } else if (String::Equals(check, factory->function_string())) {
__ JumpIfSmi(eax, if_false);
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
__ CmpObjectType(eax, JS_FUNCTION_TYPE, edx);
__ j(equal, if_true);
__ CmpInstanceType(edx, JS_FUNCTION_PROXY_TYPE);
Split(equal, if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->object_string())) {
+ } else if (String::Equals(check, factory->object_string())) {
__ JumpIfSmi(eax, if_false);
if (!FLAG_harmony_typeof) {
__ cmp(eax, isolate()->factory()->null_value());
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 66c4a5c..ebd430c 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -6094,13 +6094,13 @@
Label::Distance false_distance = right_block == next_block ? Label::kNear
: Label::kFar;
Condition final_branch_condition = no_condition;
- if (type_name->Equals(heap()->number_string())) {
+ if (String::Equals(type_name, factory()->number_string())) {
__ JumpIfSmi(input, true_label, true_distance);
__ cmp(FieldOperand(input, HeapObject::kMapOffset),
factory()->heap_number_map());
final_branch_condition = equal;
- } else if (type_name->Equals(heap()->string_string())) {
+ } else if (String::Equals(type_name, factory()->string_string())) {
__ JumpIfSmi(input, false_label, false_distance);
__ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);
__ j(above_equal, false_label, false_distance);
@@ -6108,22 +6108,23 @@
1 << Map::kIsUndetectable);
final_branch_condition = zero;
- } else if (type_name->Equals(heap()->symbol_string())) {
+ } else if (String::Equals(type_name, factory()->symbol_string())) {
__ JumpIfSmi(input, false_label, false_distance);
__ CmpObjectType(input, SYMBOL_TYPE, input);
final_branch_condition = equal;
- } else if (type_name->Equals(heap()->boolean_string())) {
+ } else if (String::Equals(type_name, factory()->boolean_string())) {
__ cmp(input, factory()->true_value());
__ j(equal, true_label, true_distance);
__ cmp(input, factory()->false_value());
final_branch_condition = equal;
- } else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_string())) {
+ } else if (FLAG_harmony_typeof &&
+ String::Equals(type_name, factory()->null_string())) {
__ cmp(input, factory()->null_value());
final_branch_condition = equal;
- } else if (type_name->Equals(heap()->undefined_string())) {
+ } else if (String::Equals(type_name, factory()->undefined_string())) {
__ cmp(input, factory()->undefined_value());
__ j(equal, true_label, true_distance);
__ JumpIfSmi(input, false_label, false_distance);
@@ -6133,7 +6134,7 @@
1 << Map::kIsUndetectable);
final_branch_condition = not_zero;
- } else if (type_name->Equals(heap()->function_string())) {
+ } else if (String::Equals(type_name, factory()->function_string())) {
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
__ JumpIfSmi(input, false_label, false_distance);
__ CmpObjectType(input, JS_FUNCTION_TYPE, input);
@@ -6141,7 +6142,7 @@
__ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE);
final_branch_condition = equal;
- } else if (type_name->Equals(heap()->object_string())) {
+ } else if (String::Equals(type_name, factory()->object_string())) {
__ JumpIfSmi(input, false_label, false_distance);
if (!FLAG_harmony_typeof) {
__ cmp(input, factory()->null_value());
diff --git a/src/ic.cc b/src/ic.cc
index 261d2e6..a5936c6 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -435,6 +435,42 @@
}
+void IC::RegisterWeakMapDependency(Handle<Code> stub) {
+ if (FLAG_collect_maps && FLAG_weak_embedded_maps_in_ic &&
+ stub->CanBeWeakStub()) {
+ ASSERT(!stub->is_weak_stub());
+ MapHandleList maps;
+ stub->FindAllMaps(&maps);
+ if (maps.length() == 1 && stub->IsWeakObjectInIC(*maps.at(0))) {
+ maps.at(0)->AddDependentIC(stub);
+ stub->mark_as_weak_stub();
+ if (FLAG_enable_ool_constant_pool) {
+ stub->constant_pool()->set_weak_object_state(
+ ConstantPoolArray::WEAK_OBJECTS_IN_IC);
+ }
+ }
+ }
+}
+
+
+void IC::InvalidateMaps(Code* stub) {
+ ASSERT(stub->is_weak_stub());
+ stub->mark_as_invalidated_weak_stub();
+ Isolate* isolate = stub->GetIsolate();
+ Heap* heap = isolate->heap();
+ Object* undefined = heap->undefined_value();
+ int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
+ for (RelocIterator it(stub, mode_mask); !it.done(); it.next()) {
+ RelocInfo::Mode mode = it.rinfo()->rmode();
+ if (mode == RelocInfo::EMBEDDED_OBJECT &&
+ it.rinfo()->target_object()->IsMap()) {
+ it.rinfo()->set_target_object(undefined, SKIP_WRITE_BARRIER);
+ }
+ }
+ CPU::FlushICache(stub->instruction_start(), stub->instruction_size());
+}
+
+
void IC::Clear(Isolate* isolate, Address address,
ConstantPoolArray* constant_pool) {
Code* target = GetTargetAtAddress(address, constant_pool);
@@ -547,7 +583,7 @@
if (FLAG_use_ic) {
// Use specialized code for getting prototype of functions.
if (object->IsJSFunction() &&
- name->Equals(isolate()->heap()->prototype_string()) &&
+ String::Equals(isolate()->factory()->prototype_string(), name) &&
Handle<JSFunction>::cast(object)->should_have_prototype()) {
Handle<Code> stub;
if (state() == UNINITIALIZED) {
@@ -890,13 +926,14 @@
Handle<String> name,
Handle<Object> unused,
InlineCacheHolderFlag cache_holder) {
- if (object->IsString() && name->Equals(isolate()->heap()->length_string())) {
+ if (object->IsString() &&
+ String::Equals(isolate()->factory()->length_string(), name)) {
int length_index = String::kLengthOffset / kPointerSize;
return SimpleFieldLoad(length_index);
}
if (object->IsStringWrapper() &&
- name->Equals(isolate()->heap()->length_string())) {
+ String::Equals(isolate()->factory()->length_string(), name)) {
if (kind() == Code::LOAD_IC) {
StringLengthStub string_length_stub;
return string_length_stub.GetCode(isolate());
@@ -1216,7 +1253,7 @@
// The length property of string values is read-only. Throw in strict mode.
if (strict_mode() == STRICT && object->IsString() &&
- name->Equals(isolate()->heap()->length_string())) {
+ String::Equals(isolate()->factory()->length_string(), name)) {
return TypeError("strict_read_only_property", object, name);
}
@@ -1403,7 +1440,7 @@
// properties. Slow properties might indicate redefinition of the length
// property.
if (receiver->IsJSArray() &&
- name->Equals(isolate()->heap()->length_string()) &&
+ String::Equals(isolate()->factory()->length_string(), name) &&
Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() &&
receiver->HasFastProperties()) {
return compiler.CompileStoreArrayLength(receiver, lookup, name);
@@ -2397,10 +2434,10 @@
Object* builtin = isolate()->js_builtins_object()->javascript_builtin(
TokenToJSBuiltin(state.op()));
Handle<JSFunction> function = handle(JSFunction::cast(builtin), isolate());
- bool caught_exception;
- Handle<Object> result = Execution::Call(
- isolate(), function, left, 1, &right, &caught_exception);
- if (caught_exception) return Failure::Exception();
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate(), result,
+ Execution::Call(isolate(), function, left, 1, &right));
// Execution::Call can execute arbitrary JavaScript, hence potentially
// update the state of this very IC, so we must update the stored state.
diff --git a/src/ic.h b/src/ic.h
index 41882e6..ca03988 100644
--- a/src/ic.h
+++ b/src/ic.h
@@ -106,6 +106,14 @@
return false;
}
+ // If the stub contains weak maps then this function adds the stub to
+ // the dependent code array of each weak map.
+ static void RegisterWeakMapDependency(Handle<Code> stub);
+
+ // This function is called when a weak map in the stub is dying,
+ // invalidates the stub by setting maps in it to undefined.
+ static void InvalidateMaps(Code* stub);
+
// Clear the inline cache to initial state.
static void Clear(Isolate* isolate,
Address address,
@@ -173,6 +181,9 @@
// Set the call-site target.
void set_target(Code* code) {
+#ifdef VERIFY_HEAP
+ code->VerifyEmbeddedObjectsDependency();
+#endif
SetTargetAtAddress(address(), code, constant_pool());
target_set_ = true;
}
diff --git a/src/isolate.cc b/src/isolate.cc
index 492e97e..3b38422 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -850,8 +850,8 @@
// constructor. Instead, we copy the pre-constructed boilerplate and
// attach the stack trace as a hidden property.
Handle<String> key = factory()->stack_overflow_string();
- Handle<JSObject> boilerplate =
- Handle<JSObject>::cast(Object::GetProperty(js_builtins_object(), key));
+ Handle<JSObject> boilerplate = Handle<JSObject>::cast(
+ Object::GetProperty(js_builtins_object(), key).ToHandleChecked());
Handle<JSObject> exception = JSObject::Copy(boilerplate);
DoThrow(*exception, NULL);
@@ -859,9 +859,13 @@
Handle<Object> error =
GetProperty(js_builtins_object(), "$Error").ToHandleChecked();
if (!error->IsJSObject()) return Failure::Exception();
+
+ Handle<String> stackTraceLimit =
+ factory()->InternalizeUtf8String("stackTraceLimit");
+ ASSERT(!stackTraceLimit.is_null());
Handle<Object> stack_trace_limit =
- GetProperty(
- Handle<JSObject>::cast(error), "stackTraceLimit").ToHandleChecked();
+ JSObject::GetDataProperty(Handle<JSObject>::cast(error),
+ stackTraceLimit);
if (!stack_trace_limit->IsNumber()) return Failure::Exception();
double dlimit = stack_trace_limit->Number();
int limit = std::isnan(dlimit) ? 0 : static_cast<int>(dlimit);
@@ -1050,8 +1054,8 @@
Handle<String> error_key =
factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("$Error"));
- Handle<Object> error_constructor = GlobalObject::GetPropertyNoExceptionThrown(
- js_builtins_object(), error_key);
+ Handle<Object> error_constructor = Object::GetProperty(
+ js_builtins_object(), error_key).ToHandleChecked();
DisallowHeapAllocation no_gc;
for (Object* prototype = *obj; !prototype->IsNull();
@@ -1131,10 +1135,9 @@
// before throwing as uncaught exception. Note that the pending
// exception object to be set later must not be turned into a string.
if (exception_arg->IsJSObject() && !IsErrorObject(exception_arg)) {
- bool failed = false;
- exception_arg =
- Execution::ToDetailString(this, exception_arg, &failed);
- if (failed) {
+ MaybeHandle<Object> maybe_exception =
+ Execution::ToDetailString(this, exception_arg);
+ if (!maybe_exception.ToHandle(&exception_arg)) {
exception_arg = factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR("exception"));
}
diff --git a/src/json-parser.h b/src/json-parser.h
index 5d8033a..a7dbd3a 100644
--- a/src/json-parser.h
+++ b/src/json-parser.h
@@ -539,17 +539,16 @@
if (seq_ascii) {
Vector<const uint8_t> chars(seq_source_->GetChars() + beg_pos, length);
number = StringToDouble(isolate()->unicode_cache(),
- Vector<const char>::cast(chars),
- NO_FLAGS, // Hex, octal or trailing junk.
- OS::nan_value());
+ chars,
+ NO_FLAGS, // Hex, octal or trailing junk.
+ OS::nan_value());
} else {
Vector<uint8_t> buffer = Vector<uint8_t>::New(length);
String::WriteToFlat(*source_, buffer.start(), beg_pos, position_);
Vector<const uint8_t> result =
Vector<const uint8_t>(buffer.start(), length);
number = StringToDouble(isolate()->unicode_cache(),
- // TODO(dcarney): Convert StringToDouble to uint_t.
- Vector<const char>::cast(result),
+ result,
NO_FLAGS, // Hex, octal or trailing junk.
0.0);
buffer.Dispose();
diff --git a/src/json-stringifier.h b/src/json-stringifier.h
index e50f11b..bbc80f2 100644
--- a/src/json-stringifier.h
+++ b/src/json-stringifier.h
@@ -378,11 +378,11 @@
// Call toJSON function.
if (key->IsSmi()) key = factory_->NumberToString(key);
Handle<Object> argv[] = { key };
- bool has_exception = false;
HandleScope scope(isolate_);
- object = Execution::Call(isolate_, fun, object, 1, argv, &has_exception);
- // Return empty handle to signal an exception.
- if (has_exception) return MaybeHandle<Object>();
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate_, object,
+ Execution::Call(isolate_, fun, object, 1, argv),
+ Object);
return scope.CloseAndEscape(object);
}
@@ -486,10 +486,11 @@
GetProperty(builtins, "JSONSerializeAdapter").ToHandleChecked());
Handle<Object> argv[] = { key, object };
- bool has_exception = false;
- Handle<Object> result =
- Execution::Call(isolate_, builtin, object, 2, argv, &has_exception);
- if (has_exception) return EXCEPTION;
+ Handle<Object> result;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate_, result,
+ Execution::Call(isolate_, builtin, object, 2, argv),
+ EXCEPTION);
if (result->IsUndefined()) return UNCHANGED;
if (deferred_key) {
if (key->IsSmi()) key = factory_->NumberToString(key);
@@ -515,17 +516,16 @@
BasicJsonStringifier::Result BasicJsonStringifier::SerializeJSValue(
Handle<JSValue> object) {
- bool has_exception = false;
String* class_name = object->class_name();
if (class_name == isolate_->heap()->String_string()) {
- Handle<Object> value =
- Execution::ToString(isolate_, object, &has_exception);
- if (has_exception) return EXCEPTION;
+ Handle<Object> value;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate_, value, Execution::ToString(isolate_, object), EXCEPTION);
SerializeString(Handle<String>::cast(value));
} else if (class_name == isolate_->heap()->Number_string()) {
- Handle<Object> value =
- Execution::ToNumber(isolate_, object, &has_exception);
- if (has_exception) return EXCEPTION;
+ Handle<Object> value;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate_, value, Execution::ToNumber(isolate_, object), EXCEPTION);
if (value->IsSmi()) return SerializeSmi(Smi::cast(*value));
SerializeHeapNumber(Handle<HeapNumber>::cast(value));
} else {
diff --git a/src/jsregexp.cc b/src/jsregexp.cc
index ab553c3..35b3996 100644
--- a/src/jsregexp.cc
+++ b/src/jsregexp.cc
@@ -66,14 +66,13 @@
namespace v8 {
namespace internal {
-Handle<Object> RegExpImpl::CreateRegExpLiteral(Handle<JSFunction> constructor,
- Handle<String> pattern,
- Handle<String> flags,
- bool* has_pending_exception) {
+MaybeHandle<Object> RegExpImpl::CreateRegExpLiteral(
+ Handle<JSFunction> constructor,
+ Handle<String> pattern,
+ Handle<String> flags) {
// Call the construct code with 2 arguments.
Handle<Object> argv[] = { pattern, flags };
- return Execution::New(constructor, ARRAY_SIZE(argv), argv,
- has_pending_exception);
+ return Execution::New(constructor, ARRAY_SIZE(argv), argv);
}
diff --git a/src/jsregexp.h b/src/jsregexp.h
index dfd415d..a0b526b 100644
--- a/src/jsregexp.h
+++ b/src/jsregexp.h
@@ -55,10 +55,10 @@
// Creates a regular expression literal in the old space.
// This function calls the garbage collector if necessary.
- static Handle<Object> CreateRegExpLiteral(Handle<JSFunction> constructor,
- Handle<String> pattern,
- Handle<String> flags,
- bool* has_pending_exception);
+ MUST_USE_RESULT static MaybeHandle<Object> CreateRegExpLiteral(
+ Handle<JSFunction> constructor,
+ Handle<String> pattern,
+ Handle<String> flags);
// Returns a string representation of a regular expression.
// Implements RegExp.prototype.toString, see ECMA-262 section 15.10.6.4.
diff --git a/src/lithium-codegen.cc b/src/lithium-codegen.cc
index 1fbb251..3cd16db 100644
--- a/src/lithium-codegen.cc
+++ b/src/lithium-codegen.cc
@@ -211,7 +211,7 @@
NoWeakObjectVerificationScope disable_verification_of_embedded_objects;
#endif
for (int i = 0; i < maps.length(); i++) {
- maps.at(i)->AddDependentCode(DependentCode::kWeaklyEmbeddedGroup, code);
+ maps.at(i)->AddDependentCode(DependentCode::kWeakCodeGroup, code);
}
for (int i = 0; i < objects.length(); i++) {
AddWeakObjectToCodeDependency(isolate()->heap(), objects.at(i), code);
diff --git a/src/liveedit.cc b/src/liveedit.cc
index c6a460c..dbb06f2 100644
--- a/src/liveedit.cc
+++ b/src/liveedit.cc
@@ -724,8 +724,8 @@
HandleScope scope(isolate());
FunctionInfoWrapper info =
FunctionInfoWrapper::cast(
- *Object::GetElementNoExceptionThrown(
- isolate(), result_, current_parent_index_));
+ *Object::GetElement(
+ isolate(), result_, current_parent_index_).ToHandleChecked());
current_parent_index_ = info.GetParentIndex();
}
@@ -734,8 +734,8 @@
void FunctionCode(Handle<Code> function_code) {
FunctionInfoWrapper info =
FunctionInfoWrapper::cast(
- *Object::GetElementNoExceptionThrown(
- isolate(), result_, current_parent_index_));
+ *Object::GetElement(
+ isolate(), result_, current_parent_index_).ToHandleChecked());
info.SetFunctionCode(function_code,
Handle<HeapObject>(isolate()->heap()->null_value()));
}
@@ -749,8 +749,8 @@
}
FunctionInfoWrapper info =
FunctionInfoWrapper::cast(
- *Object::GetElementNoExceptionThrown(
- isolate(), result_, current_parent_index_));
+ *Object::GetElement(
+ isolate(), result_, current_parent_index_).ToHandleChecked());
info.SetFunctionCode(Handle<Code>(shared->code()),
Handle<HeapObject>(shared->scope_info()));
info.SetSharedFunctionInfo(shared);
@@ -881,7 +881,7 @@
for (int i = 0; i < len; i++) {
Handle<SharedFunctionInfo> info(
SharedFunctionInfo::cast(
- *Object::GetElementNoExceptionThrown(isolate, array, i)));
+ *Object::GetElement(isolate, array, i).ToHandleChecked()));
SharedInfoWrapper info_wrapper = SharedInfoWrapper::Create(isolate);
Handle<String> name_handle(String::cast(info->name()));
info_wrapper.SetProperties(name_handle, info->start_position(),
@@ -1239,21 +1239,21 @@
// TODO(635): binary search may be used here
for (int i = 0; i < array_len; i += 3) {
HandleScope scope(isolate);
- Handle<Object> element = Object::GetElementNoExceptionThrown(
- isolate, position_change_array, i);
+ Handle<Object> element = Object::GetElement(
+ isolate, position_change_array, i).ToHandleChecked();
CHECK(element->IsSmi());
int chunk_start = Handle<Smi>::cast(element)->value();
if (original_position < chunk_start) {
break;
}
- element = Object::GetElementNoExceptionThrown(
- isolate, position_change_array, i + 1);
+ element = Object::GetElement(
+ isolate, position_change_array, i + 1).ToHandleChecked();
CHECK(element->IsSmi());
int chunk_end = Handle<Smi>::cast(element)->value();
// Position mustn't be inside a chunk.
ASSERT(original_position >= chunk_end);
- element = Object::GetElementNoExceptionThrown(
- isolate, position_change_array, i + 2);
+ element = Object::GetElement(
+ isolate, position_change_array, i + 2).ToHandleChecked();
CHECK(element->IsSmi());
int chunk_changed_end = Handle<Smi>::cast(element)->value();
position_diff = chunk_changed_end - chunk_end;
@@ -1504,7 +1504,7 @@
for (int i = 0; i < len; i++) {
HandleScope scope(isolate);
Handle<Object> element =
- Object::GetElementNoExceptionThrown(isolate, shared_info_array, i);
+ Object::GetElement(isolate, shared_info_array, i).ToHandleChecked();
Handle<JSValue> jsvalue = Handle<JSValue>::cast(element);
Handle<SharedFunctionInfo> shared =
UnwrapSharedFunctionInfoFromJSValue(jsvalue);
@@ -1821,7 +1821,7 @@
// Replace "blocked on active" with "replaced on active" status.
for (int i = 0; i < array_len; i++) {
Handle<Object> obj =
- Object::GetElementNoExceptionThrown(isolate, result, i);
+ Object::GetElement(isolate, result, i).ToHandleChecked();
if (*obj == Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
Handle<Object> replaced(
Smi::FromInt(LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK), isolate);
diff --git a/src/liveedit.h b/src/liveedit.h
index df2280d..4833f0f 100644
--- a/src/liveedit.h
+++ b/src/liveedit.h
@@ -216,8 +216,8 @@
}
Handle<Object> GetField(int field_position) {
- return Object::GetElementNoExceptionThrown(
- isolate(), array_, field_position);
+ return Object::GetElement(
+ isolate(), array_, field_position).ToHandleChecked();
}
int GetSmiValueField(int field_position) {
@@ -297,8 +297,8 @@
public:
static bool IsInstance(Handle<JSArray> array) {
return array->length() == Smi::FromInt(kSize_) &&
- Object::GetElementNoExceptionThrown(
- array->GetIsolate(), array, kSharedInfoOffset_)->IsJSValue();
+ Object::GetElement(array->GetIsolate(), array, kSharedInfoOffset_)
+ .ToHandleChecked()->IsJSValue();
}
explicit SharedInfoWrapper(Handle<JSArray> array)
diff --git a/src/log.cc b/src/log.cc
index f8ed2e9..896350e 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -1208,8 +1208,8 @@
i++;
ASSERT('0' <= format[i] && format[i] <= '9');
// No exception expected when getting an element from an array literal.
- Handle<Object> obj =
- Object::GetElementNoExceptionThrown(isolate_, args, format[i] - '0');
+ Handle<Object> obj = Object::GetElement(
+ isolate_, args, format[i] - '0').ToHandleChecked();
i++;
switch (format[i]) {
case 's':
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index 04c36f7..7eeb244 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -449,7 +449,7 @@
#ifdef VERIFY_HEAP
if (heap()->weak_embedded_objects_verification_enabled()) {
- VerifyWeakEmbeddedObjectsInOptimizedCode();
+ VerifyWeakEmbeddedObjectsInCode();
}
if (FLAG_collect_maps && FLAG_omit_map_checks_for_leaf_maps) {
VerifyOmittedMapChecks();
@@ -510,13 +510,13 @@
}
-void MarkCompactCollector::VerifyWeakEmbeddedObjectsInOptimizedCode() {
+void MarkCompactCollector::VerifyWeakEmbeddedObjectsInCode() {
HeapObjectIterator code_iterator(heap()->code_space());
for (HeapObject* obj = code_iterator.Next();
obj != NULL;
obj = code_iterator.Next()) {
Code* code = Code::cast(obj);
- if (code->kind() != Code::OPTIMIZED_FUNCTION) continue;
+ if (!code->is_optimized_code() && !code->is_weak_stub()) continue;
if (WillBeDeoptimized(code)) continue;
code->VerifyEmbeddedObjectsDependency();
}
@@ -2583,7 +2583,7 @@
if (map_mark.Get()) {
ClearNonLiveDependentCode(map->dependent_code());
} else {
- ClearAndDeoptimizeDependentCode(map->dependent_code());
+ ClearDependentCode(map->dependent_code());
map->set_dependent_code(DependentCode::cast(heap()->empty_fixed_array()));
}
}
@@ -2638,7 +2638,7 @@
}
ClearNonLiveDependentCode(DependentCode::cast(value));
} else {
- ClearAndDeoptimizeDependentCode(DependentCode::cast(value));
+ ClearDependentCode(DependentCode::cast(value));
table->set(key_index, heap_->the_hole_value());
table->set(value_index, heap_->the_hole_value());
}
@@ -2708,28 +2708,91 @@
}
-void MarkCompactCollector::ClearAndDeoptimizeDependentCode(
+void MarkCompactCollector::ClearDependentICList(Object* head) {
+ Object* current = head;
+ Object* undefined = heap()->undefined_value();
+ while (current != undefined) {
+ Code* code = Code::cast(current);
+ if (IsMarked(code)) {
+ ASSERT(code->is_weak_stub());
+ IC::InvalidateMaps(code);
+ }
+ current = code->next_code_link();
+ code->set_next_code_link(undefined);
+ }
+}
+
+
+void MarkCompactCollector::ClearDependentCode(
DependentCode* entries) {
DisallowHeapAllocation no_allocation;
DependentCode::GroupStartIndexes starts(entries);
int number_of_entries = starts.number_of_entries();
if (number_of_entries == 0) return;
- for (int i = 0; i < number_of_entries; i++) {
+ int g = DependentCode::kWeakICGroup;
+ if (starts.at(g) != starts.at(g + 1)) {
+ int i = starts.at(g);
+ ASSERT(i + 1 == starts.at(g + 1));
+ Object* head = entries->object_at(i);
+ ClearDependentICList(head);
+ }
+ g = DependentCode::kWeakCodeGroup;
+ for (int i = starts.at(g); i < starts.at(g + 1); i++) {
// If the entry is compilation info then the map must be alive,
- // and ClearAndDeoptimizeDependentCode shouldn't be called.
+ // and ClearDependentCode shouldn't be called.
ASSERT(entries->is_code_at(i));
Code* code = entries->code_at(i);
-
if (IsMarked(code) && !code->marked_for_deoptimization()) {
code->set_marked_for_deoptimization(true);
code->InvalidateEmbeddedObjects();
have_code_to_deoptimize_ = true;
}
+ }
+ for (int i = 0; i < number_of_entries; i++) {
entries->clear_at(i);
}
}
+int MarkCompactCollector::ClearNonLiveDependentCodeInGroup(
+ DependentCode* entries, int group, int start, int end, int new_start) {
+ int survived = 0;
+ if (group == DependentCode::kWeakICGroup) {
+ // Dependent weak IC stubs form a linked list and only the head is stored
+ // in the dependent code array.
+ if (start != end) {
+ ASSERT(start + 1 == end);
+ Object* old_head = entries->object_at(start);
+ MarkCompactWeakObjectRetainer retainer;
+ Object* head = VisitWeakList<Code>(heap(), old_head, &retainer, true);
+ entries->set_object_at(new_start, head);
+ Object** slot = entries->slot_at(new_start);
+ RecordSlot(slot, slot, head);
+ // We do not compact this group even if the head is undefined,
+ // more dependent ICs are likely to be added later.
+ survived = 1;
+ }
+ } else {
+ for (int i = start; i < end; i++) {
+ Object* obj = entries->object_at(i);
+ ASSERT(obj->IsCode() || IsMarked(obj));
+ if (IsMarked(obj) &&
+ (!obj->IsCode() || !WillBeDeoptimized(Code::cast(obj)))) {
+ if (new_start + survived != i) {
+ entries->set_object_at(new_start + survived, obj);
+ }
+ Object** slot = entries->slot_at(new_start + survived);
+ RecordSlot(slot, slot, obj);
+ survived++;
+ }
+ }
+ }
+ entries->set_number_of_entries(
+ static_cast<DependentCode::DependencyGroup>(group), survived);
+ return survived;
+}
+
+
void MarkCompactCollector::ClearNonLiveDependentCode(DependentCode* entries) {
DisallowHeapAllocation no_allocation;
DependentCode::GroupStartIndexes starts(entries);
@@ -2738,26 +2801,9 @@
int new_number_of_entries = 0;
// Go through all groups, remove dead codes and compact.
for (int g = 0; g < DependentCode::kGroupCount; g++) {
- int group_number_of_entries = 0;
- for (int i = starts.at(g); i < starts.at(g + 1); i++) {
- Object* obj = entries->object_at(i);
- ASSERT(obj->IsCode() || IsMarked(obj));
- if (IsMarked(obj) &&
- (!obj->IsCode() || !WillBeDeoptimized(Code::cast(obj)))) {
- if (new_number_of_entries + group_number_of_entries != i) {
- entries->set_object_at(
- new_number_of_entries + group_number_of_entries, obj);
- }
- Object** slot = entries->slot_at(new_number_of_entries +
- group_number_of_entries);
- RecordSlot(slot, slot, obj);
- group_number_of_entries++;
- }
- }
- entries->set_number_of_entries(
- static_cast<DependentCode::DependencyGroup>(g),
- group_number_of_entries);
- new_number_of_entries += group_number_of_entries;
+ int survived = ClearNonLiveDependentCodeInGroup(
+ entries, g, starts.at(g), starts.at(g + 1), new_number_of_entries);
+ new_number_of_entries += survived;
}
for (int i = new_number_of_entries; i < number_of_entries; i++) {
entries->clear_at(i);
@@ -3414,7 +3460,7 @@
// Return true if the given code is deoptimized or will be deoptimized.
bool MarkCompactCollector::WillBeDeoptimized(Code* code) {
- return code->marked_for_deoptimization();
+ return code->is_optimized_code() && code->marked_for_deoptimization();
}
diff --git a/src/mark-compact.h b/src/mark-compact.h
index 253d528..67b2ebe 100644
--- a/src/mark-compact.h
+++ b/src/mark-compact.h
@@ -609,7 +609,7 @@
void VerifyMarkbitsAreClean();
static void VerifyMarkbitsAreClean(PagedSpace* space);
static void VerifyMarkbitsAreClean(NewSpace* space);
- void VerifyWeakEmbeddedObjectsInOptimizedCode();
+ void VerifyWeakEmbeddedObjectsInCode();
void VerifyOmittedMapChecks();
#endif
@@ -870,8 +870,11 @@
void ClearNonLivePrototypeTransitions(Map* map);
void ClearNonLiveMapTransitions(Map* map, MarkBit map_mark);
- void ClearAndDeoptimizeDependentCode(DependentCode* dependent_code);
+ void ClearDependentCode(DependentCode* dependent_code);
+ void ClearDependentICList(Object* head);
void ClearNonLiveDependentCode(DependentCode* dependent_code);
+ int ClearNonLiveDependentCodeInGroup(DependentCode* dependent_code, int group,
+ int start, int end, int new_start);
// Marking detaches initial maps from SharedFunctionInfo objects
// to make this reference weak. We need to reattach initial maps
diff --git a/src/messages.cc b/src/messages.cc
index 0136b45..3445d4d 100644
--- a/src/messages.cc
+++ b/src/messages.cc
@@ -154,22 +154,16 @@
Factory* factory = isolate->factory();
Handle<String> fmt_str =
factory->InternalizeOneByteString(STATIC_ASCII_VECTOR("FormatMessage"));
- Handle<JSFunction> fun = Handle<JSFunction>::cast(
- GlobalObject::GetPropertyNoExceptionThrown(
- isolate->js_builtins_object(), fmt_str));
+ Handle<JSFunction> fun = Handle<JSFunction>::cast(Object::GetProperty(
+ isolate->js_builtins_object(), fmt_str).ToHandleChecked());
Handle<JSMessageObject> message = Handle<JSMessageObject>::cast(data);
Handle<Object> argv[] = { Handle<Object>(message->type(), isolate),
Handle<Object>(message->arguments(), isolate) };
- bool caught_exception;
- Handle<Object> result =
- Execution::TryCall(fun,
- isolate->js_builtins_object(),
- ARRAY_SIZE(argv),
- argv,
- &caught_exception);
-
- if (caught_exception || !result->IsString()) {
+ MaybeHandle<Object> maybe_result = Execution::TryCall(
+ fun, isolate->js_builtins_object(), ARRAY_SIZE(argv), argv);
+ Handle<Object> result;
+ if (!maybe_result.ToHandle(&result) || !result->IsString()) {
return factory->InternalizeOneByteString(STATIC_ASCII_VECTOR("<error>"));
}
Handle<String> result_string = Handle<String>::cast(result);
diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc
index dfbe37f..ef6bc84 100644
--- a/src/mips/full-codegen-mips.cc
+++ b/src/mips/full-codegen-mips.cc
@@ -4575,12 +4575,13 @@
}
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
- if (check->Equals(isolate()->heap()->number_string())) {
+ Factory* factory = isolate()->factory();
+ if (String::Equals(check, factory->number_string())) {
__ JumpIfSmi(v0, if_true);
__ lw(v0, FieldMemOperand(v0, HeapObject::kMapOffset));
__ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
Split(eq, v0, Operand(at), if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->string_string())) {
+ } else if (String::Equals(check, factory->string_string())) {
__ JumpIfSmi(v0, if_false);
// Check for undetectable objects => false.
__ GetObjectType(v0, v0, a1);
@@ -4589,20 +4590,20 @@
__ And(a1, a1, Operand(1 << Map::kIsUndetectable));
Split(eq, a1, Operand(zero_reg),
if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->symbol_string())) {
+ } else if (String::Equals(check, factory->symbol_string())) {
__ JumpIfSmi(v0, if_false);
__ GetObjectType(v0, v0, a1);
Split(eq, a1, Operand(SYMBOL_TYPE), if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->boolean_string())) {
+ } else if (String::Equals(check, factory->boolean_string())) {
__ LoadRoot(at, Heap::kTrueValueRootIndex);
__ Branch(if_true, eq, v0, Operand(at));
__ LoadRoot(at, Heap::kFalseValueRootIndex);
Split(eq, v0, Operand(at), if_true, if_false, fall_through);
} else if (FLAG_harmony_typeof &&
- check->Equals(isolate()->heap()->null_string())) {
+ String::Equals(check, factory->null_string())) {
__ LoadRoot(at, Heap::kNullValueRootIndex);
Split(eq, v0, Operand(at), if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->undefined_string())) {
+ } else if (String::Equals(check, factory->undefined_string())) {
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
__ Branch(if_true, eq, v0, Operand(at));
__ JumpIfSmi(v0, if_false);
@@ -4611,14 +4612,14 @@
__ lbu(a1, FieldMemOperand(v0, Map::kBitFieldOffset));
__ And(a1, a1, Operand(1 << Map::kIsUndetectable));
Split(ne, a1, Operand(zero_reg), if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->function_string())) {
+ } else if (String::Equals(check, factory->function_string())) {
__ JumpIfSmi(v0, if_false);
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
__ GetObjectType(v0, v0, a1);
__ Branch(if_true, eq, a1, Operand(JS_FUNCTION_TYPE));
Split(eq, a1, Operand(JS_FUNCTION_PROXY_TYPE),
if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->object_string())) {
+ } else if (String::Equals(check, factory->object_string())) {
__ JumpIfSmi(v0, if_false);
if (!FLAG_harmony_typeof) {
__ LoadRoot(at, Heap::kNullValueRootIndex);
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index 7c3f28f..dd05f7d 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -5524,7 +5524,8 @@
// register.
Condition final_branch_condition = kNoCondition;
Register scratch = scratch0();
- if (type_name->Equals(heap()->number_string())) {
+ Factory* factory = isolate()->factory();
+ if (String::Equals(type_name, factory->number_string())) {
__ JumpIfSmi(input, true_label);
__ lw(input, FieldMemOperand(input, HeapObject::kMapOffset));
__ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
@@ -5532,7 +5533,7 @@
cmp2 = Operand(at);
final_branch_condition = eq;
- } else if (type_name->Equals(heap()->string_string())) {
+ } else if (String::Equals(type_name, factory->string_string())) {
__ JumpIfSmi(input, false_label);
__ GetObjectType(input, input, scratch);
__ Branch(USE_DELAY_SLOT, false_label,
@@ -5545,14 +5546,14 @@
cmp2 = Operand(zero_reg);
final_branch_condition = eq;
- } else if (type_name->Equals(heap()->symbol_string())) {
+ } else if (String::Equals(type_name, factory->symbol_string())) {
__ JumpIfSmi(input, false_label);
__ GetObjectType(input, input, scratch);
cmp1 = scratch;
cmp2 = Operand(SYMBOL_TYPE);
final_branch_condition = eq;
- } else if (type_name->Equals(heap()->boolean_string())) {
+ } else if (String::Equals(type_name, factory->boolean_string())) {
__ LoadRoot(at, Heap::kTrueValueRootIndex);
__ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input));
__ LoadRoot(at, Heap::kFalseValueRootIndex);
@@ -5560,13 +5561,14 @@
cmp2 = Operand(input);
final_branch_condition = eq;
- } else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_string())) {
+ } else if (FLAG_harmony_typeof &&
+ String::Equals(type_name, factory->null_string())) {
__ LoadRoot(at, Heap::kNullValueRootIndex);
cmp1 = at;
cmp2 = Operand(input);
final_branch_condition = eq;
- } else if (type_name->Equals(heap()->undefined_string())) {
+ } else if (String::Equals(type_name, factory->undefined_string())) {
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
__ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input));
// The first instruction of JumpIfSmi is an And - it is safe in the delay
@@ -5580,7 +5582,7 @@
cmp2 = Operand(zero_reg);
final_branch_condition = ne;
- } else if (type_name->Equals(heap()->function_string())) {
+ } else if (String::Equals(type_name, factory->function_string())) {
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
__ JumpIfSmi(input, false_label);
__ GetObjectType(input, scratch, input);
@@ -5589,7 +5591,7 @@
cmp2 = Operand(JS_FUNCTION_PROXY_TYPE);
final_branch_condition = eq;
- } else if (type_name->Equals(heap()->object_string())) {
+ } else if (String::Equals(type_name, factory->object_string())) {
__ JumpIfSmi(input, false_label);
if (!FLAG_harmony_typeof) {
__ LoadRoot(at, Heap::kNullValueRootIndex);
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index 0f92780..bacf422 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -663,19 +663,21 @@
void Code::VerifyEmbeddedObjectsDependency() {
+ if (!CanContainWeakObjects()) return;
int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
Object* obj = it.rinfo()->target_object();
if (IsWeakObject(obj)) {
if (obj->IsMap()) {
Map* map = Map::cast(obj);
- CHECK(map->dependent_code()->Contains(
- DependentCode::kWeaklyEmbeddedGroup, this));
+ DependentCode::DependencyGroup group = is_optimized_code() ?
+ DependentCode::kWeakCodeGroup : DependentCode::kWeakICGroup;
+ CHECK(map->dependent_code()->Contains(group, this));
} else if (obj->IsJSObject()) {
Object* raw_table = GetIsolate()->heap()->weak_object_to_code_table();
WeakHashTable* table = WeakHashTable::cast(raw_table);
CHECK(DependentCode::cast(table->Lookup(obj))->Contains(
- DependentCode::kWeaklyEmbeddedGroup, this));
+ DependentCode::kWeakCodeGroup, this));
}
}
}
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 461578b..ed66dc6 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -1081,6 +1081,13 @@
}
+MaybeHandle<Object> Object::GetProperty(Handle<Object> object,
+ Handle<Name> name) {
+ PropertyAttributes attributes;
+ return GetPropertyWithReceiver(object, object, name, &attributes);
+}
+
+
MaybeHandle<Object> Object::GetElement(Isolate* isolate,
Handle<Object> object,
uint32_t index) {
@@ -1092,19 +1099,39 @@
}
-Handle<Object> Object::GetElementNoExceptionThrown(Isolate* isolate,
- Handle<Object> object,
- uint32_t index) {
- Handle<Object> result =
- Object::GetElementWithReceiver(
- isolate, object, object, index).ToHandleChecked();
- return result;
+MaybeHandle<Object> Object::GetPropertyOrElement(Handle<Object> object,
+ Handle<Name> name) {
+ uint32_t index;
+ Isolate* isolate = name->GetIsolate();
+ if (name->AsArrayIndex(&index)) return GetElement(isolate, object, index);
+ return GetProperty(object, name);
}
-MaybeObject* Object::GetProperty(Name* key) {
- PropertyAttributes attributes;
- return GetPropertyWithReceiver(this, key, &attributes);
+MaybeHandle<Object> JSProxy::GetElementWithHandler(Handle<JSProxy> proxy,
+ Handle<Object> receiver,
+ uint32_t index) {
+ return GetPropertyWithHandler(
+ proxy, receiver, proxy->GetIsolate()->factory()->Uint32ToString(index));
+}
+
+
+MaybeHandle<Object> JSProxy::SetElementWithHandler(Handle<JSProxy> proxy,
+ Handle<JSReceiver> receiver,
+ uint32_t index,
+ Handle<Object> value,
+ StrictMode strict_mode) {
+ Isolate* isolate = proxy->GetIsolate();
+ Handle<String> name = isolate->factory()->Uint32ToString(index);
+ return SetPropertyWithHandler(
+ proxy, receiver, name, value, NONE, strict_mode);
+}
+
+
+bool JSProxy::HasElementWithHandler(Handle<JSProxy> proxy, uint32_t index) {
+ Isolate* isolate = proxy->GetIsolate();
+ Handle<String> name = isolate->factory()->Uint32ToString(index);
+ return HasPropertyWithHandler(proxy, name);
}
@@ -2835,7 +2862,7 @@
}
-DescriptorArray::WhitenessWitness::WhitenessWitness(FixedArray* array)
+DescriptorArray::WhitenessWitness::WhitenessWitness(DescriptorArray* array)
: marking_(array->GetHeap()->incremental_marking()) {
marking_->EnterNoMarkingScope();
ASSERT(!marking_->IsMarking() ||
@@ -3024,15 +3051,6 @@
}
-Handle<Object> GlobalObject::GetPropertyNoExceptionThrown(
- Handle<GlobalObject> global,
- Handle<Name> name) {
- Handle<Object> result = Object::GetProperty(global, name);
- CHECK_NOT_EMPTY_HANDLE(name->GetIsolate(), result);
- return result;
-}
-
-
bool Name::Equals(Name* other) {
if (other == this) return true;
if ((this->IsInternalizedString() && other->IsInternalizedString()) ||
@@ -3043,6 +3061,17 @@
}
+bool Name::Equals(Handle<Name> one, Handle<Name> two) {
+ if (one.is_identical_to(two)) return true;
+ if ((one->IsInternalizedString() && two->IsInternalizedString()) ||
+ one->IsSymbol() || two->IsSymbol()) {
+ return false;
+ }
+ return String::SlowEquals(Handle<String>::cast(one),
+ Handle<String>::cast(two));
+}
+
+
ACCESSORS(Symbol, name, Object, kNameOffset)
ACCESSORS(Symbol, flags, Smi, kFlagsOffset)
BOOL_ACCESSORS(Symbol, flags, is_private, kPrivateBit)
@@ -3057,6 +3086,15 @@
}
+bool String::Equals(Handle<String> one, Handle<String> two) {
+ if (one.is_identical_to(two)) return true;
+ if (one->IsInternalizedString() && two->IsInternalizedString()) {
+ return false;
+ }
+ return SlowEquals(one, two);
+}
+
+
Handle<String> String::Flatten(Handle<String> string, PretenureFlag pretenure) {
if (!string->IsConsString()) return string;
Handle<ConsString> cons = Handle<ConsString>::cast(string);
@@ -3065,22 +3103,6 @@
}
-MaybeObject* String::TryFlatten(PretenureFlag pretenure) {
- if (!StringShape(this).IsCons()) return this;
- ConsString* cons = ConsString::cast(this);
- if (cons->IsFlat()) return cons->first();
- return SlowTryFlatten(pretenure);
-}
-
-
-String* String::TryFlattenGetString(PretenureFlag pretenure) {
- MaybeObject* flat = TryFlatten(pretenure);
- Object* successfully_flattened;
- if (!flat->ToObject(&successfully_flattened)) return this;
- return String::cast(successfully_flattened);
-}
-
-
uint16_t String::Get(int index) {
ASSERT(index >= 0 && index < length());
switch (StringShape(this).full_representation_tag()) {
@@ -4767,6 +4789,34 @@
}
+bool Code::is_weak_stub() {
+ return CanBeWeakStub() && WeakStubField::decode(
+ READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
+}
+
+
+void Code::mark_as_weak_stub() {
+ ASSERT(CanBeWeakStub());
+ int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
+ int updated = WeakStubField::update(previous, true);
+ WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
+}
+
+
+bool Code::is_invalidated_weak_stub() {
+ return is_weak_stub() && InvalidatedWeakStubField::decode(
+ READ_UINT32_FIELD(this, kKindSpecificFlags1Offset));
+}
+
+
+void Code::mark_as_invalidated_weak_stub() {
+ ASSERT(is_inline_cache_stub());
+ int previous = READ_UINT32_FIELD(this, kKindSpecificFlags1Offset);
+ int updated = InvalidatedWeakStubField::update(previous, true);
+ WRITE_UINT32_FIELD(this, kKindSpecificFlags1Offset, updated);
+}
+
+
bool Code::is_inline_cache_stub() {
Kind kind = this->kind();
switch (kind) {
@@ -4910,6 +4960,13 @@
};
+bool Code::IsWeakObjectInIC(Object* object) {
+ return object->IsMap() && Map::cast(object)->CanTransition() &&
+ FLAG_collect_maps &&
+ FLAG_weak_embedded_maps_in_ic;
+}
+
+
Object* Map::prototype() {
return READ_FIELD(this, kPrototypeOffset);
}
@@ -4924,21 +4981,17 @@
// If the descriptor is using the empty transition array, install a new empty
// transition array that will have place for an element transition.
-static MaybeObject* EnsureHasTransitionArray(Map* map) {
- TransitionArray* transitions;
- MaybeObject* maybe_transitions;
+static void EnsureHasTransitionArray(Handle<Map> map) {
+ Handle<TransitionArray> transitions;
if (!map->HasTransitionArray()) {
- maybe_transitions = TransitionArray::Allocate(map->GetIsolate(), 0);
- if (!maybe_transitions->To(&transitions)) return maybe_transitions;
+ transitions = TransitionArray::Allocate(map->GetIsolate(), 0);
transitions->set_back_pointer_storage(map->GetBackPointer());
} else if (!map->transitions()->IsFullTransitionArray()) {
- maybe_transitions = map->transitions()->ExtendToFullTransitionArray();
- if (!maybe_transitions->To(&transitions)) return maybe_transitions;
+ transitions = TransitionArray::ExtendToFullTransitionArray(map);
} else {
- return map;
+ return;
}
- map->set_transitions(transitions);
- return transitions;
+ map->set_transitions(*transitions);
}
@@ -4979,12 +5032,11 @@
}
-void Map::AppendDescriptor(Descriptor* desc,
- const DescriptorArray::WhitenessWitness& witness) {
+void Map::AppendDescriptor(Descriptor* desc) {
DescriptorArray* descriptors = instance_descriptors();
int number_of_own_descriptors = NumberOfOwnDescriptors();
ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors);
- descriptors->Append(desc, witness);
+ descriptors->Append(desc);
SetNumberOfOwnDescriptors(number_of_own_descriptors + 1);
}
@@ -5050,19 +5102,18 @@
}
-MaybeObject* Map::SetPrototypeTransitions(FixedArray* proto_transitions) {
- MaybeObject* allow_prototype = EnsureHasTransitionArray(this);
- if (allow_prototype->IsFailure()) return allow_prototype;
- int old_number_of_transitions = NumberOfProtoTransitions();
+void Map::SetPrototypeTransitions(
+ Handle<Map> map, Handle<FixedArray> proto_transitions) {
+ EnsureHasTransitionArray(map);
+ int old_number_of_transitions = map->NumberOfProtoTransitions();
#ifdef DEBUG
- if (HasPrototypeTransitions()) {
- ASSERT(GetPrototypeTransitions() != proto_transitions);
- ZapPrototypeTransitions();
+ if (map->HasPrototypeTransitions()) {
+ ASSERT(map->GetPrototypeTransitions() != *proto_transitions);
+ map->ZapPrototypeTransitions();
}
#endif
- transitions()->SetPrototypeTransitions(proto_transitions);
- SetNumberOfProtoTransitions(old_number_of_transitions);
- return this;
+ map->transitions()->SetPrototypeTransitions(*proto_transitions);
+ map->SetNumberOfProtoTransitions(old_number_of_transitions);
}
diff --git a/src/objects-visiting-inl.h b/src/objects-visiting-inl.h
index f46adcc..169c405 100644
--- a/src/objects-visiting-inl.h
+++ b/src/objects-visiting-inl.h
@@ -312,7 +312,8 @@
if (FLAG_cleanup_code_caches_at_gc && target->is_inline_cache_stub()
&& (target->ic_state() == MEGAMORPHIC || target->ic_state() == GENERIC ||
target->ic_state() == POLYMORPHIC || heap->flush_monomorphic_ics() ||
- Serializer::enabled() || target->ic_age() != heap->global_ic_age())) {
+ Serializer::enabled() || target->ic_age() != heap->global_ic_age() ||
+ target->is_invalidated_weak_stub())) {
IC::Clear(target->GetIsolate(), rinfo->pc(),
rinfo->host()->constant_pool());
target = Code::GetCodeFromTargetAddress(rinfo->target_address());
@@ -501,9 +502,14 @@
Object** slot = constant_pool->RawFieldOfElementAt(index);
HeapObject* object = HeapObject::cast(*slot);
heap->mark_compact_collector()->RecordSlot(slot, slot, object);
- if (!(constant_pool->get_weak_object_state() ==
+ bool is_weak_object =
+ (constant_pool->get_weak_object_state() ==
ConstantPoolArray::WEAK_OBJECTS_IN_OPTIMIZED_CODE &&
- Code::IsWeakObjectInOptimizedCode(object))) {
+ Code::IsWeakObjectInOptimizedCode(object)) ||
+ (constant_pool->get_weak_object_state() ==
+ ConstantPoolArray::WEAK_OBJECTS_IN_IC &&
+ Code::IsWeakObjectInIC(object));
+ if (!is_weak_object) {
StaticVisitor::MarkObject(heap, object);
}
}
diff --git a/src/objects-visiting.cc b/src/objects-visiting.cc
index 16c5167..b314a47 100644
--- a/src/objects-visiting.cc
+++ b/src/objects-visiting.cc
@@ -211,4 +211,281 @@
}
}
+
+template <class T>
+struct WeakListVisitor;
+
+
+template <class T>
+Object* VisitWeakList(Heap* heap,
+ Object* list,
+ WeakObjectRetainer* retainer,
+ bool record_slots) {
+ Object* undefined = heap->undefined_value();
+ Object* head = undefined;
+ T* tail = NULL;
+ MarkCompactCollector* collector = heap->mark_compact_collector();
+ while (list != undefined) {
+ // Check whether to keep the candidate in the list.
+ T* candidate = reinterpret_cast<T*>(list);
+ Object* retained = retainer->RetainAs(list);
+ if (retained != NULL) {
+ if (head == undefined) {
+ // First element in the list.
+ head = retained;
+ } else {
+ // Subsequent elements in the list.
+ ASSERT(tail != NULL);
+ WeakListVisitor<T>::SetWeakNext(tail, retained);
+ if (record_slots) {
+ Object** next_slot =
+ HeapObject::RawField(tail, WeakListVisitor<T>::WeakNextOffset());
+ collector->RecordSlot(next_slot, next_slot, retained);
+ }
+ }
+ // Retained object is new tail.
+ ASSERT(!retained->IsUndefined());
+ candidate = reinterpret_cast<T*>(retained);
+ tail = candidate;
+
+
+ // tail is a live object, visit it.
+ WeakListVisitor<T>::VisitLiveObject(
+ heap, tail, retainer, record_slots);
+ } else {
+ WeakListVisitor<T>::VisitPhantomObject(heap, candidate);
+ }
+
+ // Move to next element in the list.
+ list = WeakListVisitor<T>::WeakNext(candidate);
+ }
+
+ // Terminate the list if there is one or more elements.
+ if (tail != NULL) {
+ WeakListVisitor<T>::SetWeakNext(tail, undefined);
+ }
+ return head;
+}
+
+
+template <class T>
+static void ClearWeakList(Heap* heap,
+ Object* list) {
+ Object* undefined = heap->undefined_value();
+ while (list != undefined) {
+ T* candidate = reinterpret_cast<T*>(list);
+ list = WeakListVisitor<T>::WeakNext(candidate);
+ WeakListVisitor<T>::SetWeakNext(candidate, undefined);
+ }
+}
+
+
+template<>
+struct WeakListVisitor<JSFunction> {
+ static void SetWeakNext(JSFunction* function, Object* next) {
+ function->set_next_function_link(next);
+ }
+
+ static Object* WeakNext(JSFunction* function) {
+ return function->next_function_link();
+ }
+
+ static int WeakNextOffset() {
+ return JSFunction::kNextFunctionLinkOffset;
+ }
+
+ static void VisitLiveObject(Heap*, JSFunction*,
+ WeakObjectRetainer*, bool) {
+ }
+
+ static void VisitPhantomObject(Heap*, JSFunction*) {
+ }
+};
+
+
+template<>
+struct WeakListVisitor<Code> {
+ static void SetWeakNext(Code* code, Object* next) {
+ code->set_next_code_link(next);
+ }
+
+ static Object* WeakNext(Code* code) {
+ return code->next_code_link();
+ }
+
+ static int WeakNextOffset() {
+ return Code::kNextCodeLinkOffset;
+ }
+
+ static void VisitLiveObject(Heap*, Code*,
+ WeakObjectRetainer*, bool) {
+ }
+
+ static void VisitPhantomObject(Heap*, Code*) {
+ }
+};
+
+
+template<>
+struct WeakListVisitor<Context> {
+ static void SetWeakNext(Context* context, Object* next) {
+ context->set(Context::NEXT_CONTEXT_LINK,
+ next,
+ UPDATE_WRITE_BARRIER);
+ }
+
+ static Object* WeakNext(Context* context) {
+ return context->get(Context::NEXT_CONTEXT_LINK);
+ }
+
+ static void VisitLiveObject(Heap* heap,
+ Context* context,
+ WeakObjectRetainer* retainer,
+ bool record_slots) {
+ // Process the three weak lists linked off the context.
+ DoWeakList<JSFunction>(heap, context, retainer, record_slots,
+ Context::OPTIMIZED_FUNCTIONS_LIST);
+ DoWeakList<Code>(heap, context, retainer, record_slots,
+ Context::OPTIMIZED_CODE_LIST);
+ DoWeakList<Code>(heap, context, retainer, record_slots,
+ Context::DEOPTIMIZED_CODE_LIST);
+ }
+
+ template<class T>
+ static void DoWeakList(Heap* heap,
+ Context* context,
+ WeakObjectRetainer* retainer,
+ bool record_slots,
+ int index) {
+ // Visit the weak list, removing dead intermediate elements.
+ Object* list_head = VisitWeakList<T>(heap, context->get(index), retainer,
+ record_slots);
+
+ // Update the list head.
+ context->set(index, list_head, UPDATE_WRITE_BARRIER);
+
+ if (record_slots) {
+ // Record the updated slot if necessary.
+ Object** head_slot = HeapObject::RawField(
+ context, FixedArray::SizeFor(index));
+ heap->mark_compact_collector()->RecordSlot(
+ head_slot, head_slot, list_head);
+ }
+ }
+
+ static void VisitPhantomObject(Heap* heap, Context* context) {
+ ClearWeakList<JSFunction>(heap,
+ context->get(Context::OPTIMIZED_FUNCTIONS_LIST));
+ ClearWeakList<Code>(heap, context->get(Context::OPTIMIZED_CODE_LIST));
+ ClearWeakList<Code>(heap, context->get(Context::DEOPTIMIZED_CODE_LIST));
+ }
+
+ static int WeakNextOffset() {
+ return FixedArray::SizeFor(Context::NEXT_CONTEXT_LINK);
+ }
+};
+
+
+template<>
+struct WeakListVisitor<JSArrayBufferView> {
+ static void SetWeakNext(JSArrayBufferView* obj, Object* next) {
+ obj->set_weak_next(next);
+ }
+
+ static Object* WeakNext(JSArrayBufferView* obj) {
+ return obj->weak_next();
+ }
+
+ static void VisitLiveObject(Heap*,
+ JSArrayBufferView* obj,
+ WeakObjectRetainer* retainer,
+ bool record_slots) {}
+
+ static void VisitPhantomObject(Heap*, JSArrayBufferView*) {}
+
+ static int WeakNextOffset() {
+ return JSArrayBufferView::kWeakNextOffset;
+ }
+};
+
+
+template<>
+struct WeakListVisitor<JSArrayBuffer> {
+ static void SetWeakNext(JSArrayBuffer* obj, Object* next) {
+ obj->set_weak_next(next);
+ }
+
+ static Object* WeakNext(JSArrayBuffer* obj) {
+ return obj->weak_next();
+ }
+
+ static void VisitLiveObject(Heap* heap,
+ JSArrayBuffer* array_buffer,
+ WeakObjectRetainer* retainer,
+ bool record_slots) {
+ Object* typed_array_obj =
+ VisitWeakList<JSArrayBufferView>(
+ heap,
+ array_buffer->weak_first_view(),
+ retainer, record_slots);
+ array_buffer->set_weak_first_view(typed_array_obj);
+ if (typed_array_obj != heap->undefined_value() && record_slots) {
+ Object** slot = HeapObject::RawField(
+ array_buffer, JSArrayBuffer::kWeakFirstViewOffset);
+ heap->mark_compact_collector()->RecordSlot(slot, slot, typed_array_obj);
+ }
+ }
+
+ static void VisitPhantomObject(Heap* heap, JSArrayBuffer* phantom) {
+ Runtime::FreeArrayBuffer(heap->isolate(), phantom);
+ }
+
+ static int WeakNextOffset() {
+ return JSArrayBuffer::kWeakNextOffset;
+ }
+};
+
+
+template<>
+struct WeakListVisitor<AllocationSite> {
+ static void SetWeakNext(AllocationSite* obj, Object* next) {
+ obj->set_weak_next(next);
+ }
+
+ static Object* WeakNext(AllocationSite* obj) {
+ return obj->weak_next();
+ }
+
+ static void VisitLiveObject(Heap* heap,
+ AllocationSite* site,
+ WeakObjectRetainer* retainer,
+ bool record_slots) {}
+
+ static void VisitPhantomObject(Heap* heap, AllocationSite* phantom) {}
+
+ static int WeakNextOffset() {
+ return AllocationSite::kWeakNextOffset;
+ }
+};
+
+
+template Object* VisitWeakList<Code>(
+ Heap* heap, Object* list, WeakObjectRetainer* retainer, bool record_slots);
+
+
+template Object* VisitWeakList<JSFunction>(
+ Heap* heap, Object* list, WeakObjectRetainer* retainer, bool record_slots);
+
+
+template Object* VisitWeakList<Context>(
+ Heap* heap, Object* list, WeakObjectRetainer* retainer, bool record_slots);
+
+
+template Object* VisitWeakList<JSArrayBuffer>(
+ Heap* heap, Object* list, WeakObjectRetainer* retainer, bool record_slots);
+
+
+template Object* VisitWeakList<AllocationSite>(
+ Heap* heap, Object* list, WeakObjectRetainer* retainer, bool record_slots);
+
} } // namespace v8::internal
diff --git a/src/objects-visiting.h b/src/objects-visiting.h
index de8ca6d..910334b 100644
--- a/src/objects-visiting.h
+++ b/src/objects-visiting.h
@@ -483,6 +483,20 @@
StaticMarkingVisitor<StaticVisitor>::table_;
+class WeakObjectRetainer;
+
+
+// A weak list is single linked list where each element has a weak pointer to
+// the next element. Given the head of the list, this function removes dead
+// elements from the list and if requested records slots for next-element
+// pointers. The template parameter T is a WeakListVisitor that defines how to
+// access the next-element pointers.
+template <class T>
+Object* VisitWeakList(Heap* heap,
+ Object* list,
+ WeakObjectRetainer* retainer,
+ bool record_slots);
+
} } // namespace v8::internal
#endif // V8_OBJECTS_VISITING_H_
diff --git a/src/objects.cc b/src/objects.cc
index f66275a..aaa0320 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -170,17 +170,6 @@
}
-MaybeObject* Object::GetPropertyWithReceiver(Object* receiver,
- Name* name,
- PropertyAttributes* attributes) {
- LookupResult result(name->GetIsolate());
- Lookup(name, &result);
- MaybeObject* value = GetProperty(receiver, &result, name, attributes);
- ASSERT(*attributes <= ABSENT);
- return value;
-}
-
-
bool Object::ToInt32(int32_t* value) {
if (IsSmi()) {
*value = Smi::cast(this)->value();
@@ -474,69 +463,17 @@
}
-MaybeObject* JSProxy::GetPropertyWithHandler(Object* receiver_raw,
- Name* name_raw) {
- Isolate* isolate = GetIsolate();
- HandleScope scope(isolate);
- Handle<Object> receiver(receiver_raw, isolate);
- Handle<Object> name(name_raw, isolate);
+MaybeHandle<Object> JSProxy::GetPropertyWithHandler(Handle<JSProxy> proxy,
+ Handle<Object> receiver,
+ Handle<Name> name) {
+ Isolate* isolate = proxy->GetIsolate();
// TODO(rossberg): adjust once there is a story for symbols vs proxies.
- if (name->IsSymbol()) return isolate->heap()->undefined_value();
+ if (name->IsSymbol()) return isolate->factory()->undefined_value();
Handle<Object> args[] = { receiver, name };
- Handle<Object> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result,
- CallTrap(handle(this),
- "get",
- isolate->derived_get_trap(),
- ARRAY_SIZE(args),
- args));
- return *result;
-}
-
-
-MaybeHandle<Object> Object::GetPropertyOrElement(Handle<Object> object,
- Handle<Name> name) {
- uint32_t index;
- Isolate* isolate = name->GetIsolate();
- if (name->AsArrayIndex(&index)) return GetElement(isolate, object, index);
- return GetProperty(object, name);
-}
-
-
-Handle<Object> Object::GetProperty(Handle<Object> object,
- Handle<Name> name) {
- CALL_HEAP_FUNCTION(name->GetIsolate(), object->GetProperty(*name), Object);
-}
-
-
-MaybeObject* JSProxy::GetElementWithHandler(Object* receiver,
- uint32_t index) {
- String* name;
- MaybeObject* maybe = GetHeap()->Uint32ToString(index);
- if (!maybe->To<String>(&name)) return maybe;
- return GetPropertyWithHandler(receiver, name);
-}
-
-
-MaybeHandle<Object> JSProxy::SetElementWithHandler(Handle<JSProxy> proxy,
- Handle<JSReceiver> receiver,
- uint32_t index,
- Handle<Object> value,
- StrictMode strict_mode) {
- Isolate* isolate = proxy->GetIsolate();
- Handle<String> name = isolate->factory()->Uint32ToString(index);
- return SetPropertyWithHandler(
- proxy, receiver, name, value, NONE, strict_mode);
-}
-
-
-bool JSProxy::HasElementWithHandler(Handle<JSProxy> proxy, uint32_t index) {
- Isolate* isolate = proxy->GetIsolate();
- Handle<String> name = isolate->factory()->Uint32ToString(index);
- return HasPropertyWithHandler(proxy, name);
+ return CallTrap(
+ proxy, "get", isolate->derived_get_trap(), ARRAY_SIZE(args), args);
}
@@ -555,12 +492,7 @@
}
#endif
- bool has_pending_exception;
- Handle<Object> result = Execution::Call(
- isolate, getter, receiver, 0, NULL, &has_pending_exception, true);
- // Check for pending exception and return the result.
- if (has_pending_exception) return MaybeHandle<Object>();
- return result;
+ return Execution::Call(isolate, getter, receiver, 0, NULL, true);
}
@@ -700,6 +632,20 @@
}
+Handle<Object> JSObject::GetNormalizedProperty(Handle<JSObject> object,
+ const LookupResult* result) {
+ ASSERT(!object->HasFastProperties());
+ Isolate* isolate = object->GetIsolate();
+ Handle<Object> value(object->property_dictionary()->ValueAt(
+ result->GetDictionaryEntry()), isolate);
+ if (object->IsGlobalObject()) {
+ value = Handle<Object>(Handle<PropertyCell>::cast(value)->value(), isolate);
+ }
+ ASSERT(!value->IsPropertyCell() && !value->IsCell());
+ return value;
+}
+
+
void JSObject::SetNormalizedProperty(Handle<JSObject> object,
const LookupResult* result,
Handle<Object> value) {
@@ -841,29 +787,10 @@
MaybeHandle<Object> Object::GetProperty(Handle<Object> object,
Handle<Object> receiver,
LookupResult* result,
- Handle<Name> key,
+ Handle<Name> name,
PropertyAttributes* attributes) {
- Isolate* isolate = result->isolate();
- CALL_HEAP_FUNCTION(
- isolate,
- object->GetProperty(*receiver, result, *key, attributes),
- Object);
-}
-
-
-// TODO(yangguo): handlify this and get rid of.
-MaybeObject* Object::GetProperty(Object* receiver,
- LookupResult* result,
- Name* name,
- PropertyAttributes* attributes) {
Isolate* isolate = name->GetIsolate();
- Heap* heap = isolate->heap();
-
-#ifdef DEBUG
- // TODO(mstarzinger): Only because of the AssertNoContextChange, drop as soon
- // as this method has been fully handlified.
- HandleScope scope(isolate);
-#endif
+ Factory* factory = isolate->factory();
// Make sure that the top context does not change when doing
// callbacks or interceptor calls.
@@ -877,93 +804,70 @@
// holder in the prototype chain.
// Proxy handlers do not use the proxy's prototype, so we can skip this.
if (!result->IsHandler()) {
- Object* last = result->IsProperty()
- ? result->holder()
- : Object::cast(heap->null_value());
- ASSERT(this != this->GetPrototype(isolate));
- for (Object* current = this;
+ ASSERT(*object != object->GetPrototype(isolate));
+ Handle<Object> last = result->IsProperty()
+ ? Handle<Object>(result->holder(), isolate)
+ : Handle<Object>::cast(factory->null_value());
+ for (Handle<Object> current = object;
true;
- current = current->GetPrototype(isolate)) {
+ current = Handle<Object>(current->GetPrototype(isolate), isolate)) {
if (current->IsAccessCheckNeeded()) {
// Check if we're allowed to read from the current object. Note
// that even though we may not actually end up loading the named
// property from the current object, we still check that we have
// access to it.
- JSObject* checked = JSObject::cast(current);
- if (!isolate->MayNamedAccess(checked, name, v8::ACCESS_GET)) {
- HandleScope scope(isolate);
- Handle<Object> value;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, value,
- JSObject::GetPropertyWithFailedAccessCheck(
- handle(checked, isolate),
- handle(receiver, isolate),
- result,
- handle(name, isolate),
- attributes));
- return *value;
+ Handle<JSObject> checked = Handle<JSObject>::cast(current);
+ if (!isolate->MayNamedAccessWrapper(checked, name, v8::ACCESS_GET)) {
+ return JSObject::GetPropertyWithFailedAccessCheck(
+ checked, receiver, result, name, attributes);
}
}
// Stop traversing the chain once we reach the last object in the
// chain; either the holder of the result or null in case of an
// absent property.
- if (current == last) break;
+ if (current.is_identical_to(last)) break;
}
}
if (!result->IsProperty()) {
*attributes = ABSENT;
- return heap->undefined_value();
+ return factory->undefined_value();
}
*attributes = result->GetAttributes();
- Object* value;
+
+ Handle<Object> value;
switch (result->type()) {
- case NORMAL:
- value = result->holder()->GetNormalizedProperty(result);
- ASSERT(!value->IsTheHole() || result->IsReadOnly());
- return value->IsTheHole() ? heap->undefined_value() : value;
- case FIELD: {
- MaybeObject* maybe_result = result->holder()->FastPropertyAt(
- result->representation(),
- result->GetFieldIndex().field_index());
- if (!maybe_result->To(&value)) return maybe_result;
- ASSERT(!value->IsTheHole() || result->IsReadOnly());
- return value->IsTheHole() ? heap->undefined_value() : value;
+ case NORMAL: {
+ DisallowHeapAllocation no_gc;
+ value = handle(result->holder()->GetNormalizedProperty(result), isolate);
+ break;
}
+ case FIELD:
+ value = JSObject::FastPropertyAt(handle(result->holder(), isolate),
+ result->representation(),
+ result->GetFieldIndex().field_index());
+ break;
case CONSTANT:
- return result->GetConstant();
- case CALLBACKS: {
- HandleScope scope(isolate);
- Handle<Object> value;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, value,
- JSObject::GetPropertyWithCallback(
- handle(result->holder(), isolate),
- handle(receiver, isolate),
- handle(result->GetCallbackObject(), isolate),
- handle(name, isolate)));
- return *value;
- }
+ return handle(result->GetConstant(), isolate);
+ case CALLBACKS:
+ return JSObject::GetPropertyWithCallback(
+ handle(result->holder(), isolate),
+ receiver,
+ handle(result->GetCallbackObject(), isolate),
+ name);
case HANDLER:
- return result->proxy()->GetPropertyWithHandler(receiver, name);
- case INTERCEPTOR: {
- HandleScope scope(isolate);
- Handle<Object> value;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, value,
- JSObject::GetPropertyWithInterceptor(
- handle(result->holder(), isolate),
- handle(receiver, isolate),
- handle(name, isolate),
- attributes));
- return *value;
- }
+ return JSProxy::GetPropertyWithHandler(
+ handle(result->proxy(), isolate), receiver, name);
+ case INTERCEPTOR:
+ return JSObject::GetPropertyWithInterceptor(
+ handle(result->holder(), isolate), receiver, name, attributes);
case NONEXISTENT:
UNREACHABLE();
break;
}
- UNREACHABLE();
- return NULL;
+ ASSERT(!value->IsTheHole() || result->IsReadOnly());
+ return value->IsTheHole() ? Handle<Object>::cast(factory->undefined_value())
+ : value;
}
@@ -993,10 +897,8 @@
holder = Handle<Object>(
native_context->boolean_function()->instance_prototype(), isolate);
} else if (holder->IsJSProxy()) {
- CALL_HEAP_FUNCTION(isolate,
- Handle<JSProxy>::cast(holder)->GetElementWithHandler(
- *receiver, index),
- Object);
+ return JSProxy::GetElementWithHandler(
+ Handle<JSProxy>::cast(holder), receiver, index);
} else {
// Undefined and null have no indexed properties.
ASSERT(holder->IsUndefined() || holder->IsNull());
@@ -1214,73 +1116,11 @@
}
cons->set_first(*result);
cons->set_second(isolate->heap()->empty_string());
+ ASSERT(result->IsFlat());
return result;
}
-MaybeObject* String::SlowTryFlatten(PretenureFlag pretenure) {
-#ifdef DEBUG
- // Do not attempt to flatten in debug mode when allocation is not
- // allowed. This is to avoid an assertion failure when allocating.
- // Flattening strings is the only case where we always allow
- // allocation because no GC is performed if the allocation fails.
- if (!AllowHeapAllocation::IsAllowed()) return this;
-#endif
-
- Heap* heap = GetHeap();
- switch (StringShape(this).representation_tag()) {
- case kConsStringTag: {
- ConsString* cs = ConsString::cast(this);
- if (cs->second()->length() == 0) {
- return cs->first();
- }
- // There's little point in putting the flat string in new space if the
- // cons string is in old space. It can never get GCed until there is
- // an old space GC.
- PretenureFlag tenure = heap->InNewSpace(this) ? pretenure : TENURED;
- int len = length();
- Object* object;
- String* result;
- if (IsOneByteRepresentation()) {
- { MaybeObject* maybe_object =
- heap->AllocateRawOneByteString(len, tenure);
- if (!maybe_object->ToObject(&object)) return maybe_object;
- }
- result = String::cast(object);
- String* first = cs->first();
- int first_length = first->length();
- uint8_t* dest = SeqOneByteString::cast(result)->GetChars();
- WriteToFlat(first, dest, 0, first_length);
- String* second = cs->second();
- WriteToFlat(second,
- dest + first_length,
- 0,
- len - first_length);
- } else {
- { MaybeObject* maybe_object =
- heap->AllocateRawTwoByteString(len, tenure);
- if (!maybe_object->ToObject(&object)) return maybe_object;
- }
- result = String::cast(object);
- uc16* dest = SeqTwoByteString::cast(result)->GetChars();
- String* first = cs->first();
- int first_length = first->length();
- WriteToFlat(first, dest, 0, first_length);
- String* second = cs->second();
- WriteToFlat(second,
- dest + first_length,
- 0,
- len - first_length);
- }
- cs->set_first(result);
- cs->set_second(heap->empty_string(), SKIP_WRITE_BARRIER);
- return result;
- }
- default:
- return this;
- }
-}
-
bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
// Externalizing twice leaks the external resource, so it's
@@ -2213,14 +2053,11 @@
}
Handle<Object> args[] = { type, object, name, old_value };
int argc = name.is_null() ? 2 : old_value->IsTheHole() ? 3 : 4;
- bool threw;
Execution::Call(isolate,
Handle<JSFunction>(isolate->observers_notify_change()),
isolate->factory()->undefined_value(),
- argc, args,
- &threw);
- ASSERT(!threw);
+ argc, args).Assert();
}
@@ -2991,7 +2828,7 @@
}
-Handle<Object> JSReceiver::SetPropertyWithDefinedSetter(
+MaybeHandle<Object> JSReceiver::SetPropertyWithDefinedSetter(
Handle<JSReceiver> object,
Handle<JSReceiver> setter,
Handle<Object> value) {
@@ -3007,12 +2844,11 @@
}
#endif
- bool has_pending_exception;
Handle<Object> argv[] = { value };
- Execution::Call(
- isolate, setter, object, ARRAY_SIZE(argv), argv, &has_pending_exception);
- // Check for pending exception and return the result.
- if (has_pending_exception) return Handle<Object>();
+ RETURN_ON_EXCEPTION(
+ isolate,
+ Execution::Call(isolate, setter, object, ARRAY_SIZE(argv), argv),
+ Object);
return value;
}
@@ -3678,20 +3514,24 @@
}
// Emulate [[GetProperty]] semantics for proxies.
- bool has_pending_exception;
Handle<Object> argv[] = { result };
- Handle<Object> desc = Execution::Call(
- isolate, isolate->to_complete_property_descriptor(), result,
- ARRAY_SIZE(argv), argv, &has_pending_exception);
- if (has_pending_exception) return MaybeHandle<Object>();
+ Handle<Object> desc;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, desc,
+ Execution::Call(isolate,
+ isolate->to_complete_property_descriptor(),
+ result,
+ ARRAY_SIZE(argv),
+ argv),
+ Object);
// [[GetProperty]] requires to check that all properties are configurable.
Handle<String> configurable_name =
isolate->factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR("configurable_"));
- Handle<Object> configurable = Object::GetProperty(desc, configurable_name);
- ASSERT(!configurable.is_null());
- ASSERT(configurable->IsTrue() || configurable->IsFalse());
+ Handle<Object> configurable =
+ Object::GetProperty(desc, configurable_name).ToHandleChecked();
+ ASSERT(configurable->IsBoolean());
if (configurable->IsFalse()) {
Handle<String> trap =
isolate->factory()->InternalizeOneByteString(
@@ -3707,16 +3547,16 @@
Handle<String> hasWritable_name =
isolate->factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR("hasWritable_"));
- Handle<Object> hasWritable = Object::GetProperty(desc, hasWritable_name);
- ASSERT(!hasWritable.is_null());
- ASSERT(hasWritable->IsTrue() || hasWritable->IsFalse());
+ Handle<Object> hasWritable =
+ Object::GetProperty(desc, hasWritable_name).ToHandleChecked();
+ ASSERT(hasWritable->IsBoolean());
if (hasWritable->IsTrue()) {
Handle<String> writable_name =
isolate->factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR("writable_"));
- Handle<Object> writable = Object::GetProperty(desc, writable_name);
- ASSERT(!writable.is_null());
- ASSERT(writable->IsTrue() || writable->IsFalse());
+ Handle<Object> writable =
+ Object::GetProperty(desc, writable_name).ToHandleChecked();
+ ASSERT(writable->IsBoolean());
*done = writable->IsFalse();
if (!*done) return isolate->factory()->the_hole_value();
if (strict_mode == SLOPPY) return value;
@@ -3729,8 +3569,7 @@
// We have an AccessorDescriptor.
Handle<String> set_name = isolate->factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR("set_"));
- Handle<Object> setter = Object::GetProperty(desc, set_name);
- ASSERT(!setter.is_null());
+ Handle<Object> setter = Object::GetProperty(desc, set_name).ToHandleChecked();
if (!setter->IsUndefined()) {
// TODO(rossberg): nicer would be to cast to some JSCallable here...
return SetPropertyWithDefinedSetter(
@@ -3808,31 +3647,39 @@
if (result->IsUndefined()) return ABSENT;
- bool has_pending_exception;
Handle<Object> argv[] = { result };
- Handle<Object> desc = Execution::Call(
- isolate, isolate->to_complete_property_descriptor(), result,
- ARRAY_SIZE(argv), argv, &has_pending_exception);
- if (has_pending_exception) return NONE;
+ Handle<Object> desc;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate, desc,
+ Execution::Call(isolate,
+ isolate->to_complete_property_descriptor(),
+ result,
+ ARRAY_SIZE(argv),
+ argv),
+ NONE);
// Convert result to PropertyAttributes.
Handle<String> enum_n = isolate->factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR("enumerable_"));
- Handle<Object> enumerable = Object::GetProperty(desc, enum_n);
- RETURN_IF_EMPTY_HANDLE_VALUE(isolate, enumerable, NONE);
+ Handle<Object> enumerable;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate, enumerable, Object::GetProperty(desc, enum_n), NONE);
Handle<String> conf_n = isolate->factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR("configurable_"));
- Handle<Object> configurable = Object::GetProperty(desc, conf_n);
- RETURN_IF_EMPTY_HANDLE_VALUE(isolate, configurable, NONE);
+ Handle<Object> configurable;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate, configurable, Object::GetProperty(desc, conf_n), NONE);
Handle<String> writ_n = isolate->factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR("writable_"));
- Handle<Object> writable = Object::GetProperty(desc, writ_n);
- RETURN_IF_EMPTY_HANDLE_VALUE(isolate, writable, NONE);
+ Handle<Object> writable;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate, writable, Object::GetProperty(desc, writ_n), NONE);
if (!writable->BooleanValue()) {
Handle<String> set_n = isolate->factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR("set_"));
- Handle<Object> setter = Object::GetProperty(desc, set_n);
- RETURN_IF_EMPTY_HANDLE_VALUE(isolate, setter, NONE);
+ Handle<Object> setter;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate, setter, Object::GetProperty(desc, set_n), NONE);
writable = isolate->factory()->ToBoolean(!setter->IsUndefined());
}
@@ -3912,8 +3759,7 @@
trap = Handle<Object>(derived);
}
- bool threw;
- return Execution::Call(isolate, trap, handler, argc, argv, &threw);
+ return Execution::Call(isolate, trap, handler, argc, argv);
}
@@ -4020,7 +3866,6 @@
static void SetPropertyToField(LookupResult* lookup,
- Handle<Name> name,
Handle<Object> value) {
Representation representation = lookup->representation();
if (!lookup->CanHoldValue(value) ||
@@ -4083,7 +3928,7 @@
PropertyAttributes attributes) {
if (lookup->GetAttributes() == attributes) {
if (value->IsUninitialized()) return;
- SetPropertyToField(lookup, name, value);
+ SetPropertyToField(lookup, value);
} else {
ConvertAndSetLocalProperty(lookup, name, value, attributes);
}
@@ -4178,12 +4023,12 @@
SetNormalizedProperty(handle(lookup->holder()), lookup, value);
break;
case FIELD:
- SetPropertyToField(lookup, name, value);
+ SetPropertyToField(lookup, value);
break;
case CONSTANT:
// Only replace the constant if necessary.
if (*value == lookup->GetConstant()) return value;
- SetPropertyToField(lookup, name, value);
+ SetPropertyToField(lookup, value);
break;
case CALLBACKS: {
Handle<Object> callback_object(lookup->GetCallbackObject(), isolate);
@@ -4761,10 +4606,136 @@
int unused_property_fields) {
if (object->HasFastProperties()) return;
ASSERT(!object->IsGlobalObject());
- CALL_HEAP_FUNCTION_VOID(
- object->GetIsolate(),
- object->property_dictionary()->TransformPropertiesToFastFor(
- *object, unused_property_fields));
+ Isolate* isolate = object->GetIsolate();
+ Factory* factory = isolate->factory();
+ Handle<NameDictionary> dictionary(object->property_dictionary());
+
+ // Make sure we preserve dictionary representation if there are too many
+ // descriptors.
+ int number_of_elements = dictionary->NumberOfElements();
+ if (number_of_elements > kMaxNumberOfDescriptors) return;
+
+ if (number_of_elements != dictionary->NextEnumerationIndex()) {
+ NameDictionary::DoGenerateNewEnumerationIndices(dictionary);
+ }
+
+ int instance_descriptor_length = 0;
+ int number_of_fields = 0;
+
+ // Compute the length of the instance descriptor.
+ int capacity = dictionary->Capacity();
+ for (int i = 0; i < capacity; i++) {
+ Object* k = dictionary->KeyAt(i);
+ if (dictionary->IsKey(k)) {
+ Object* value = dictionary->ValueAt(i);
+ PropertyType type = dictionary->DetailsAt(i).type();
+ ASSERT(type != FIELD);
+ instance_descriptor_length++;
+ if (type == NORMAL && !value->IsJSFunction()) {
+ number_of_fields += 1;
+ }
+ }
+ }
+
+ int inobject_props = object->map()->inobject_properties();
+
+ // Allocate new map.
+ Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
+ new_map->set_dictionary_map(false);
+
+ if (instance_descriptor_length == 0) {
+ DisallowHeapAllocation no_gc;
+ ASSERT_LE(unused_property_fields, inobject_props);
+ // Transform the object.
+ new_map->set_unused_property_fields(inobject_props);
+ object->set_map(*new_map);
+ object->set_properties(isolate->heap()->empty_fixed_array());
+ // Check that it really works.
+ ASSERT(object->HasFastProperties());
+ return;
+ }
+
+ // Allocate the instance descriptor.
+ Handle<DescriptorArray> descriptors = DescriptorArray::Allocate(
+ isolate, instance_descriptor_length);
+
+ int number_of_allocated_fields =
+ number_of_fields + unused_property_fields - inobject_props;
+ if (number_of_allocated_fields < 0) {
+ // There is enough inobject space for all fields (including unused).
+ number_of_allocated_fields = 0;
+ unused_property_fields = inobject_props - number_of_fields;
+ }
+
+ // Allocate the fixed array for the fields.
+ Handle<FixedArray> fields = factory->NewFixedArray(
+ number_of_allocated_fields);
+
+ // Fill in the instance descriptor and the fields.
+ int current_offset = 0;
+ for (int i = 0; i < capacity; i++) {
+ Object* k = dictionary->KeyAt(i);
+ if (dictionary->IsKey(k)) {
+ Object* value = dictionary->ValueAt(i);
+ Handle<Name> key;
+ if (k->IsSymbol()) {
+ key = handle(Symbol::cast(k));
+ } else {
+ // Ensure the key is a unique name before writing into the
+ // instance descriptor.
+ key = factory->InternalizeString(handle(String::cast(k)));
+ }
+
+ PropertyDetails details = dictionary->DetailsAt(i);
+ int enumeration_index = details.dictionary_index();
+ PropertyType type = details.type();
+
+ if (value->IsJSFunction()) {
+ ConstantDescriptor d(key,
+ handle(value, isolate),
+ details.attributes());
+ descriptors->Set(enumeration_index - 1, &d);
+ } else if (type == NORMAL) {
+ if (current_offset < inobject_props) {
+ object->InObjectPropertyAtPut(current_offset,
+ value,
+ UPDATE_WRITE_BARRIER);
+ } else {
+ int offset = current_offset - inobject_props;
+ fields->set(offset, value);
+ }
+ FieldDescriptor d(key,
+ current_offset++,
+ details.attributes(),
+ // TODO(verwaest): value->OptimalRepresentation();
+ Representation::Tagged());
+ descriptors->Set(enumeration_index - 1, &d);
+ } else if (type == CALLBACKS) {
+ CallbacksDescriptor d(key,
+ handle(value, isolate),
+ details.attributes());
+ descriptors->Set(enumeration_index - 1, &d);
+ } else {
+ UNREACHABLE();
+ }
+ }
+ }
+ ASSERT(current_offset == number_of_fields);
+
+ descriptors->Sort();
+
+ DisallowHeapAllocation no_gc;
+ new_map->InitializeDescriptors(*descriptors);
+ new_map->set_unused_property_fields(unused_property_fields);
+
+ // Transform the object.
+ object->set_map(*new_map);
+
+ object->set_properties(*fields);
+ ASSERT(object->IsJSObject());
+
+ // Check that it really works.
+ ASSERT(object->HasFastProperties());
}
@@ -5285,7 +5256,8 @@
if (!GetLocalElementAccessorPair(object, index).is_null()) {
old_value = Handle<Object>::cast(factory->the_hole_value());
} else {
- old_value = Object::GetElementNoExceptionThrown(isolate, object, index);
+ old_value = Object::GetElement(
+ isolate, object, index).ToHandleChecked();
}
}
}
@@ -5886,8 +5858,8 @@
// In particular, don't try to copy the length attribute of
// an array.
if (attributes != NONE) continue;
- Handle<Object> value = Object::GetProperty(copy, key_string);
- CHECK_NOT_EMPTY_HANDLE(isolate, value);
+ Handle<Object> value =
+ Object::GetProperty(copy, key_string).ToHandleChecked();
if (value->IsJSObject()) {
Handle<JSObject> result = VisitElementOrProperty(
copy, Handle<JSObject>::cast(value));
@@ -5998,6 +5970,41 @@
}
+Handle<Object> JSObject::GetDataProperty(Handle<JSObject> object,
+ Handle<Name> key) {
+ Isolate* isolate = object->GetIsolate();
+ LookupResult lookup(isolate);
+ {
+ DisallowHeapAllocation no_allocation;
+ object->LookupRealNamedProperty(*key, &lookup);
+ }
+ Handle<Object> result = isolate->factory()->undefined_value();
+ if (lookup.IsFound() && !lookup.IsTransition()) {
+ switch (lookup.type()) {
+ case NORMAL:
+ result = GetNormalizedProperty(
+ Handle<JSObject>(lookup.holder(), isolate), &lookup);
+ break;
+ case FIELD:
+ result = FastPropertyAt(Handle<JSObject>(lookup.holder(), isolate),
+ lookup.representation(),
+ lookup.GetFieldIndex().field_index());
+ break;
+ case CONSTANT:
+ result = Handle<Object>(lookup.GetConstant(), isolate);
+ break;
+ case CALLBACKS:
+ case HANDLER:
+ case INTERCEPTOR:
+ break;
+ case NONEXISTENT:
+ UNREACHABLE();
+ }
+ }
+ return result;
+}
+
+
// Tests for the fast common case for property enumeration:
// - This object and all prototypes has an enum cache (which means that
// it is no proxy, has no interceptors and needs no access checks).
@@ -6071,18 +6078,6 @@
}
-AccessorDescriptor* Map::FindAccessor(Name* name) {
- DescriptorArray* descs = instance_descriptors();
- int number_of_own_descriptors = NumberOfOwnDescriptors();
- for (int i = 0; i < number_of_own_descriptors; i++) {
- if (descs->GetType(i) == CALLBACKS && name->Equals(descs->GetKey(i))) {
- return descs->GetCallbacks(i);
- }
- }
- return NULL;
-}
-
-
void JSReceiver::LocalLookup(
Name* name, LookupResult* result, bool search_hidden_prototypes) {
ASSERT(name->IsName());
@@ -6462,7 +6457,8 @@
if (is_element) {
preexists = HasLocalElement(object, index);
if (preexists && GetLocalElementAccessorPair(object, index).is_null()) {
- old_value = Object::GetElementNoExceptionThrown(isolate, object, index);
+ old_value =
+ Object::GetElement(isolate, object, index).ToHandleChecked();
}
} else {
LookupResult lookup(isolate);
@@ -6578,8 +6574,8 @@
if (result.IsFound()) {
Handle<Map> target(result.GetTransitionTarget());
int descriptor_number = target->LastAdded();
- ASSERT(target->instance_descriptors()->GetKey(descriptor_number)
- ->Equals(*name));
+ ASSERT(Name::Equals(name,
+ handle(target->instance_descriptors()->GetKey(descriptor_number))));
return TryAccessorTransition(object, target, descriptor_number,
component, accessor, attributes);
}
@@ -6769,31 +6765,20 @@
}
-Handle<Map> Map::RawCopy(Handle<Map> map,
- int instance_size) {
- CALL_HEAP_FUNCTION(map->GetIsolate(),
- map->RawCopy(instance_size),
- Map);
-}
-
-
-MaybeObject* Map::RawCopy(int instance_size) {
- Map* result;
- MaybeObject* maybe_result =
- GetHeap()->AllocateMap(instance_type(), instance_size);
- if (!maybe_result->To(&result)) return maybe_result;
-
- result->set_prototype(prototype());
- result->set_constructor(constructor());
- result->set_bit_field(bit_field());
- result->set_bit_field2(bit_field2());
- int new_bit_field3 = bit_field3();
+Handle<Map> Map::RawCopy(Handle<Map> map, int instance_size) {
+ Handle<Map> result = map->GetIsolate()->factory()->NewMap(
+ map->instance_type(), instance_size);
+ result->set_prototype(map->prototype());
+ result->set_constructor(map->constructor());
+ result->set_bit_field(map->bit_field());
+ result->set_bit_field2(map->bit_field2());
+ int new_bit_field3 = map->bit_field3();
new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true);
new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
new_bit_field3 = EnumLengthBits::update(new_bit_field3,
kInvalidEnumCacheSentinel);
new_bit_field3 = Deprecated::update(new_bit_field3, false);
- if (!is_dictionary_map()) {
+ if (!map->is_dictionary_map()) {
new_bit_field3 = IsUnstable::update(new_bit_field3, false);
}
result->set_bit_field3(new_bit_field3);
@@ -6830,23 +6815,17 @@
Handle<Map> Map::CopyDropDescriptors(Handle<Map> map) {
- CALL_HEAP_FUNCTION(map->GetIsolate(), map->CopyDropDescriptors(), Map);
-}
-
-
-MaybeObject* Map::CopyDropDescriptors() {
- Map* result;
- MaybeObject* maybe_result = RawCopy(instance_size());
- if (!maybe_result->To(&result)) return maybe_result;
+ Handle<Map> result = RawCopy(map, map->instance_size());
// Please note instance_type and instance_size are set when allocated.
- result->set_inobject_properties(inobject_properties());
- result->set_unused_property_fields(unused_property_fields());
+ result->set_inobject_properties(map->inobject_properties());
+ result->set_unused_property_fields(map->unused_property_fields());
- result->set_pre_allocated_property_fields(pre_allocated_property_fields());
+ result->set_pre_allocated_property_fields(
+ map->pre_allocated_property_fields());
result->set_is_shared(false);
- result->ClearCodeCache(GetHeap());
- NotifyLeafMapLayoutChange();
+ result->ClearCodeCache(map->GetHeap());
+ map->NotifyLeafMapLayoutChange();
return result;
}
@@ -6869,7 +6848,7 @@
if (descriptors->NumberOfSlackDescriptors() == 0) {
int old_size = descriptors->number_of_descriptors();
if (old_size == 0) {
- descriptors = map->GetIsolate()->factory()->NewDescriptorArray(0, 1);
+ descriptors = DescriptorArray::Allocate(map->GetIsolate(), 0, 1);
} else {
Map::EnsureDescriptorSlack(map, old_size < 4 ? 1 : old_size / 2);
descriptors = handle(map->instance_descriptors());
@@ -7137,7 +7116,7 @@
int size = enumeration_index;
Handle<DescriptorArray> descriptors =
- desc->GetIsolate()->factory()->NewDescriptorArray(size, slack);
+ DescriptorArray::Allocate(desc->GetIsolate(), size, slack);
DescriptorArray::WhitenessWitness witness(*descriptors);
if (attributes != NONE) {
@@ -7996,21 +7975,20 @@
#endif
-MaybeObject* DescriptorArray::Allocate(Isolate* isolate,
- int number_of_descriptors,
- int slack) {
- Heap* heap = isolate->heap();
+Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate,
+ int number_of_descriptors,
+ int slack) {
+ ASSERT(0 <= number_of_descriptors);
+ Factory* factory = isolate->factory();
// Do not use DescriptorArray::cast on incomplete object.
int size = number_of_descriptors + slack;
- if (size == 0) return heap->empty_descriptor_array();
- FixedArray* result;
+ if (size == 0) return factory->empty_descriptor_array();
// Allocate the array of keys.
- MaybeObject* maybe_array = heap->AllocateFixedArray(LengthFor(size));
- if (!maybe_array->To(&result)) return maybe_array;
+ Handle<FixedArray> result = factory->NewFixedArray(LengthFor(size));
result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors));
result->set(kEnumCacheIndex, Smi::FromInt(0));
- return result;
+ return Handle<DescriptorArray>::cast(result);
}
@@ -8074,11 +8052,13 @@
// Allocate a new descriptor array large enough to hold the required
// descriptors, with minimally the exact same size as this descriptor array.
- Factory* factory = left_map->GetIsolate()->factory();
+ Isolate* isolate = left_map->GetIsolate();
Handle<DescriptorArray> left(left_map->instance_descriptors());
Handle<DescriptorArray> right(right_map->instance_descriptors());
- Handle<DescriptorArray> result = factory->NewDescriptorArray(
- new_size, Max(new_size, right->number_of_descriptors()) - new_size);
+ Handle<DescriptorArray> result = DescriptorArray::Allocate(
+ isolate,
+ new_size,
+ Max(new_size, right->number_of_descriptors()) - new_size);
ASSERT(result->length() > left->length() ||
result->NumberOfSlackDescriptors() > 0 ||
result->number_of_descriptors() == right->number_of_descriptors());
@@ -8331,7 +8311,7 @@
} else {
start = ExternalAsciiString::cast(string)->GetChars();
}
- return FlatContent(Vector<const uint8_t>(start + offset, length));
+ return FlatContent(start + offset, length);
} else {
ASSERT(shape.encoding_tag() == kTwoByteStringTag);
const uc16* start;
@@ -8340,7 +8320,7 @@
} else {
start = ExternalTwoByteString::cast(string)->GetChars();
}
- return FlatContent(Vector<const uc16>(start + offset, length));
+ return FlatContent(start + offset, length);
}
}
@@ -8980,6 +8960,7 @@
bool String::SlowEquals(String* other) {
+ DisallowHeapAllocation no_gc;
// Fast check: negative check with lengths.
int len = length();
if (len != other->length()) return false;
@@ -9009,14 +8990,10 @@
// before we try to flatten the strings.
if (this->Get(0) != other->Get(0)) return false;
- String* lhs = this->TryFlattenGetString();
- String* rhs = other->TryFlattenGetString();
-
// TODO(dcarney): Compare all types of flat strings with a Visitor.
- if (StringShape(lhs).IsSequentialAscii() &&
- StringShape(rhs).IsSequentialAscii()) {
- const uint8_t* str1 = SeqOneByteString::cast(lhs)->GetChars();
- const uint8_t* str2 = SeqOneByteString::cast(rhs)->GetChars();
+ if (IsSeqOneByteString() && other->IsSeqOneByteString()) {
+ const uint8_t* str1 = SeqOneByteString::cast(this)->GetChars();
+ const uint8_t* str2 = SeqOneByteString::cast(other)->GetChars();
return CompareRawStringContents(str1, str2, len);
}
@@ -9024,7 +9001,57 @@
StringComparator comparator(isolate->objects_string_compare_iterator_a(),
isolate->objects_string_compare_iterator_b());
- return comparator.Equals(static_cast<unsigned>(len), lhs, rhs);
+ return comparator.Equals(static_cast<unsigned>(len), this, other);
+}
+
+
+bool String::SlowEquals(Handle<String> one, Handle<String> two) {
+ // Fast check: negative check with lengths.
+ int one_length = one->length();
+ if (one_length != two->length()) return false;
+ if (one_length == 0) return true;
+
+ // Fast check: if hash code is computed for both strings
+ // a fast negative check can be performed.
+ if (one->HasHashCode() && two->HasHashCode()) {
+#ifdef ENABLE_SLOW_ASSERTS
+ if (FLAG_enable_slow_asserts) {
+ if (one->Hash() != two->Hash()) {
+ bool found_difference = false;
+ for (int i = 0; i < one_length; i++) {
+ if (one->Get(i) != two->Get(i)) {
+ found_difference = true;
+ break;
+ }
+ }
+ ASSERT(found_difference);
+ }
+ }
+#endif
+ if (one->Hash() != two->Hash()) return false;
+ }
+
+ // We know the strings are both non-empty. Compare the first chars
+ // before we try to flatten the strings.
+ if (one->Get(0) != two->Get(0)) return false;
+
+ one = String::Flatten(one);
+ two = String::Flatten(two);
+
+ DisallowHeapAllocation no_gc;
+ String::FlatContent flat1 = one->GetFlatContent();
+ String::FlatContent flat2 = two->GetFlatContent();
+
+ if (flat1.IsAscii() && flat2.IsAscii()) {
+ return CompareRawStringContents(flat1.ToOneByteVector().start(),
+ flat2.ToOneByteVector().start(),
+ one_length);
+ } else {
+ for (int i = 0; i < one_length; i++) {
+ if (flat1.Get(i) != flat2.Get(i)) return false;
+ }
+ return true;
+ }
}
@@ -11323,7 +11350,7 @@
if (!JSObject::GetLocalElementAccessorPair(object, index).is_null()) {
value = Handle<Object>::cast(isolate->factory()->the_hole_value());
} else {
- value = Object::GetElementNoExceptionThrown(isolate, object, index);
+ value = Object::GetElement(isolate, object, index).ToHandleChecked();
}
old_values->Add(value);
indices->Add(index);
@@ -11343,12 +11370,11 @@
Handle<Object> args[] =
{ object, index_object, deleted, add_count_object };
- bool threw;
Execution::Call(isolate,
Handle<JSFunction>(isolate->observers_enqueue_splice()),
- isolate->factory()->undefined_value(), ARRAY_SIZE(args), args,
- &threw);
- ASSERT(!threw);
+ isolate->factory()->undefined_value(),
+ ARRAY_SIZE(args),
+ args).Assert();
}
@@ -11357,12 +11383,11 @@
HandleScope scope(isolate);
Handle<Object> args[] = { object };
- bool threw;
Execution::Call(isolate,
Handle<JSFunction>(isolate->observers_begin_perform_splice()),
- isolate->factory()->undefined_value(), ARRAY_SIZE(args), args,
- &threw);
- ASSERT(!threw);
+ isolate->factory()->undefined_value(),
+ ARRAY_SIZE(args),
+ args).Assert();
}
@@ -11371,12 +11396,11 @@
HandleScope scope(isolate);
Handle<Object> args[] = { object };
- bool threw;
Execution::Call(isolate,
Handle<JSFunction>(isolate->observers_end_perform_splice()),
- isolate->factory()->undefined_value(), ARRAY_SIZE(args), args,
- &threw);
- ASSERT(!threw);
+ isolate->factory()->undefined_value(),
+ ARRAY_SIZE(args),
+ args).Assert();
}
@@ -11509,10 +11533,7 @@
Factory* factory = map->GetIsolate()->factory();
cache = factory->CopySizeFixedArray(cache, transitions * 2 * step + header);
- CALL_AND_RETRY_OR_DIE(map->GetIsolate(),
- map->SetPrototypeTransitions(*cache),
- break,
- return Handle<Map>());
+ Map::SetPrototypeTransitions(map, cache);
}
// Reload number of transitions as GC might shrink them.
@@ -11566,6 +11587,21 @@
}
+void Map::AddDependentIC(Handle<Code> stub) {
+ ASSERT(stub->next_code_link()->IsUndefined());
+ int n = dependent_code()->number_of_entries(DependentCode::kWeakICGroup);
+ if (n == 0) {
+ // Slow path: insert the head of the list with possible heap allocation.
+ AddDependentCode(DependentCode::kWeakICGroup, stub);
+ } else {
+ // Fast path: link the stub to the existing head of the list without any
+ // heap allocation.
+ ASSERT(n == 1);
+ dependent_code()->AddToDependentICList(stub);
+ }
+}
+
+
DependentCode::GroupStartIndexes::GroupStartIndexes(DependentCode* entries) {
Recompute(entries);
}
@@ -11696,10 +11732,22 @@
}
+static bool CodeListContains(Object* head, Code* code) {
+ while (!head->IsUndefined()) {
+ if (head == code) return true;
+ head = Code::cast(head)->next_code_link();
+ }
+ return false;
+}
+
+
bool DependentCode::Contains(DependencyGroup group, Code* code) {
GroupStartIndexes starts(this);
int start = starts.at(group);
int end = starts.at(group + 1);
+ if (group == kWeakICGroup) {
+ return CodeListContains(object_at(start), code);
+ }
for (int i = start; i < end; i++) {
if (object_at(i) == code) return true;
}
@@ -11756,6 +11804,15 @@
}
+void DependentCode::AddToDependentICList(Handle<Code> stub) {
+ DisallowHeapAllocation no_heap_allocation;
+ GroupStartIndexes starts(this);
+ int i = starts.at(kWeakICGroup);
+ stub->set_next_code_link(object_at(i));
+ set_object_at(i, *stub);
+}
+
+
Handle<Object> JSObject::SetPrototype(Handle<JSObject> object,
Handle<Object> value,
bool skip_hidden_prototypes) {
@@ -11990,12 +12047,12 @@
}
-Handle<Object> JSObject::SetElementWithCallback(Handle<JSObject> object,
- Handle<Object> structure,
- uint32_t index,
- Handle<Object> value,
- Handle<JSObject> holder,
- StrictMode strict_mode) {
+MaybeHandle<Object> JSObject::SetElementWithCallback(Handle<JSObject> object,
+ Handle<Object> structure,
+ uint32_t index,
+ Handle<Object> value,
+ Handle<JSObject> holder,
+ StrictMode strict_mode) {
Isolate* isolate = object->GetIsolate();
// We should never get here to initialize a const with the hole
@@ -12023,7 +12080,7 @@
args.Call(call_fun,
v8::Utils::ToLocal(key),
v8::Utils::ToLocal(value));
- RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
return value;
}
@@ -12039,8 +12096,7 @@
Handle<Object> args[2] = { key, holder };
Handle<Object> error = isolate->factory()->NewTypeError(
"no_setter_in_callback", HandleVector(args, 2));
- isolate->Throw(*error);
- return Handle<Object>();
+ return isolate->Throw<Object>(error);
}
}
@@ -12048,7 +12104,7 @@
if (structure->IsDeclaredAccessorInfo()) return value;
UNREACHABLE();
- return Handle<Object>();
+ return MaybeHandle<Object>();
}
@@ -12483,11 +12539,9 @@
if (object->HasExternalArrayElements() ||
object->HasFixedTypedArrayElements()) {
if (!value->IsNumber() && !value->IsUndefined()) {
- bool has_exception;
- Handle<Object> number =
- Execution::ToNumber(isolate, value, &has_exception);
- if (has_exception) return MaybeHandle<Object>();
- value = number;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, value,
+ Execution::ToNumber(isolate, value), Object);
}
}
@@ -12544,7 +12598,7 @@
if (old_attributes != ABSENT) {
if (GetLocalElementAccessorPair(object, index).is_null()) {
- old_value = Object::GetElementNoExceptionThrown(isolate, object, index);
+ old_value = Object::GetElement(isolate, object, index).ToHandleChecked();
}
} else if (object->IsJSArray()) {
// Store old array length in case adding an element grows the array.
@@ -12593,7 +12647,7 @@
EnqueueChangeRecord(object, "reconfigure", name, old_value);
} else {
Handle<Object> new_value =
- Object::GetElementNoExceptionThrown(isolate, object, index);
+ Object::GetElement(isolate, object, index).ToHandleChecked();
bool value_changed = !old_value->SameValue(*new_value);
if (old_attributes != new_attributes) {
if (!value_changed) old_value = isolate->factory()->the_hole_value();
@@ -12806,30 +12860,9 @@
Handle<AllocationSite> site;
{
DisallowHeapAllocation no_allocation;
- // Check if there is potentially a memento behind the object. If
- // the last word of the momento is on another page we return
- // immediatelly.
- Address object_address = object->address();
- Address memento_address = object_address + JSArray::kSize;
- Address last_memento_word_address = memento_address + kPointerSize;
- if (!NewSpacePage::OnSamePage(object_address,
- last_memento_word_address)) {
- return;
- }
- // 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 top = heap->NewSpaceTop();
- ASSERT(memento_address == top ||
- memento_address + HeapObject::kHeaderSize <= top);
- if (memento_address == top) return;
-
- HeapObject* candidate = HeapObject::FromAddress(memento_address);
- if (candidate->map() != heap->allocation_memento_map()) return;
-
- AllocationMemento* memento = AllocationMemento::cast(candidate);
- if (!memento->IsValid()) return;
+ AllocationMemento* memento = heap->FindAllocationMemento(*object);
+ if (memento == NULL) return;
// Walk through to the Allocation Site
site = handle(memento->GetAllocationSite());
@@ -15591,151 +15624,6 @@
}
-MaybeObject* NameDictionary::TransformPropertiesToFastFor(
- JSObject* obj, int unused_property_fields) {
- // Make sure we preserve dictionary representation if there are too many
- // descriptors.
- int number_of_elements = NumberOfElements();
- if (number_of_elements > kMaxNumberOfDescriptors) return obj;
-
- if (number_of_elements != NextEnumerationIndex()) {
- MaybeObject* maybe_result = GenerateNewEnumerationIndices();
- if (maybe_result->IsFailure()) return maybe_result;
- }
-
- int instance_descriptor_length = 0;
- int number_of_fields = 0;
-
- Heap* heap = GetHeap();
-
- // Compute the length of the instance descriptor.
- int capacity = Capacity();
- for (int i = 0; i < capacity; i++) {
- Object* k = KeyAt(i);
- if (IsKey(k)) {
- Object* value = ValueAt(i);
- PropertyType type = DetailsAt(i).type();
- ASSERT(type != FIELD);
- instance_descriptor_length++;
- if (type == NORMAL && !value->IsJSFunction()) {
- number_of_fields += 1;
- }
- }
- }
-
- int inobject_props = obj->map()->inobject_properties();
-
- // Allocate new map.
- Map* new_map;
- MaybeObject* maybe_new_map = obj->map()->CopyDropDescriptors();
- if (!maybe_new_map->To(&new_map)) return maybe_new_map;
- new_map->set_dictionary_map(false);
-
- if (instance_descriptor_length == 0) {
- ASSERT_LE(unused_property_fields, inobject_props);
- // Transform the object.
- new_map->set_unused_property_fields(inobject_props);
- obj->set_map(new_map);
- obj->set_properties(heap->empty_fixed_array());
- // Check that it really works.
- ASSERT(obj->HasFastProperties());
- return obj;
- }
-
- // Allocate the instance descriptor.
- DescriptorArray* descriptors;
- MaybeObject* maybe_descriptors =
- DescriptorArray::Allocate(GetIsolate(), instance_descriptor_length);
- if (!maybe_descriptors->To(&descriptors)) {
- return maybe_descriptors;
- }
-
- DescriptorArray::WhitenessWitness witness(descriptors);
-
- int number_of_allocated_fields =
- number_of_fields + unused_property_fields - inobject_props;
- if (number_of_allocated_fields < 0) {
- // There is enough inobject space for all fields (including unused).
- number_of_allocated_fields = 0;
- unused_property_fields = inobject_props - number_of_fields;
- }
-
- // Allocate the fixed array for the fields.
- FixedArray* fields;
- MaybeObject* maybe_fields =
- heap->AllocateFixedArray(number_of_allocated_fields);
- if (!maybe_fields->To(&fields)) return maybe_fields;
-
- // Fill in the instance descriptor and the fields.
- int current_offset = 0;
- for (int i = 0; i < capacity; i++) {
- Object* k = KeyAt(i);
- if (IsKey(k)) {
- Object* value = ValueAt(i);
- Name* key;
- if (k->IsSymbol()) {
- key = Symbol::cast(k);
- } else {
- // Ensure the key is a unique name before writing into the
- // instance descriptor.
- MaybeObject* maybe_key = heap->InternalizeString(String::cast(k));
- if (!maybe_key->To(&key)) return maybe_key;
- }
-
- PropertyDetails details = DetailsAt(i);
- int enumeration_index = details.dictionary_index();
- PropertyType type = details.type();
-
- if (value->IsJSFunction()) {
- ConstantDescriptor d(handle(key),
- handle(value, GetIsolate()),
- details.attributes());
- descriptors->Set(enumeration_index - 1, &d, witness);
- } else if (type == NORMAL) {
- if (current_offset < inobject_props) {
- obj->InObjectPropertyAtPut(current_offset,
- value,
- UPDATE_WRITE_BARRIER);
- } else {
- int offset = current_offset - inobject_props;
- fields->set(offset, value);
- }
- FieldDescriptor d(handle(key),
- current_offset++,
- details.attributes(),
- // TODO(verwaest): value->OptimalRepresentation();
- Representation::Tagged());
- descriptors->Set(enumeration_index - 1, &d, witness);
- } else if (type == CALLBACKS) {
- CallbacksDescriptor d(handle(key),
- handle(value, GetIsolate()),
- details.attributes());
- descriptors->Set(enumeration_index - 1, &d, witness);
- } else {
- UNREACHABLE();
- }
- }
- }
- ASSERT(current_offset == number_of_fields);
-
- descriptors->Sort();
-
- new_map->InitializeDescriptors(descriptors);
- new_map->set_unused_property_fields(unused_property_fields);
-
- // Transform the object.
- obj->set_map(new_map);
-
- obj->set_properties(fields);
- ASSERT(obj->IsJSObject());
-
- // Check that it really works.
- ASSERT(obj->HasFastProperties());
-
- return obj;
-}
-
-
Handle<ObjectHashTable> ObjectHashTable::EnsureCapacity(
Handle<ObjectHashTable> table,
int n,
diff --git a/src/objects.h b/src/objects.h
index c8b2753..1f656bc 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -1533,26 +1533,18 @@
void Lookup(Name* name, LookupResult* result);
- // Property access.
- MUST_USE_RESULT inline MaybeObject* GetProperty(Name* key);
-
- // TODO(yangguo): this should eventually replace the non-handlified version.
MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithReceiver(
Handle<Object> object,
Handle<Object> receiver,
Handle<Name> name,
PropertyAttributes* attributes);
- MUST_USE_RESULT MaybeObject* GetPropertyWithReceiver(
- Object* receiver,
- Name* key,
- PropertyAttributes* attributes);
-
- MUST_USE_RESULT static MaybeHandle<Object> GetPropertyOrElement(
+ MUST_USE_RESULT static inline MaybeHandle<Object> GetPropertyOrElement(
Handle<Object> object,
Handle<Name> key);
- static Handle<Object> GetProperty(Handle<Object> object,
- Handle<Name> key);
+ MUST_USE_RESULT static inline MaybeHandle<Object> GetProperty(
+ Handle<Object> object,
+ Handle<Name> key);
MUST_USE_RESULT static MaybeHandle<Object> GetProperty(
Handle<Object> object,
Handle<Object> receiver,
@@ -1560,11 +1552,6 @@
Handle<Name> key,
PropertyAttributes* attributes);
- MUST_USE_RESULT MaybeObject* GetProperty(Object* receiver,
- LookupResult* result,
- Name* key,
- PropertyAttributes* attributes);
-
MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithDefinedGetter(
Handle<Object> object,
Handle<Object> receiver,
@@ -1575,12 +1562,6 @@
Handle<Object> object,
uint32_t index);
- // For use when we know that no exception can be thrown.
- static inline Handle<Object> GetElementNoExceptionThrown(
- Isolate* isolate,
- Handle<Object> object,
- uint32_t index);
-
MUST_USE_RESULT static MaybeHandle<Object> GetElementWithReceiver(
Isolate* isolate,
Handle<Object> object,
@@ -2130,9 +2111,10 @@
protected:
Smi* GenerateIdentityHash();
- static Handle<Object> SetPropertyWithDefinedSetter(Handle<JSReceiver> object,
- Handle<JSReceiver> setter,
- Handle<Object> value);
+ MUST_USE_RESULT static MaybeHandle<Object> SetPropertyWithDefinedSetter(
+ Handle<JSReceiver> object,
+ Handle<JSReceiver> setter,
+ Handle<Object> value);
private:
static PropertyAttributes GetPropertyAttributeForResult(
@@ -2321,6 +2303,8 @@
// Retrieve a value in a normalized object given a lookup result.
// Handles the special representation of JS global objects.
Object* GetNormalizedProperty(const LookupResult* result);
+ static Handle<Object> GetNormalizedProperty(Handle<JSObject> object,
+ const LookupResult* result);
// Sets the property value in a normalized object given a lookup result.
// Handles the special representation of JS global objects.
@@ -2672,6 +2656,9 @@
static Handle<JSObject> DeepWalk(Handle<JSObject> object,
AllocationSiteCreationContext* site_context);
+ static Handle<Object> GetDataProperty(Handle<JSObject> object,
+ Handle<Name> key);
+
// Casting.
static inline JSObject* cast(Object* obj);
@@ -2811,7 +2798,7 @@
Handle<JSReceiver> receiver,
uint32_t index,
bool continue_search);
- static Handle<Object> SetElementWithCallback(
+ MUST_USE_RESULT static MaybeHandle<Object> SetElementWithCallback(
Handle<JSObject> object,
Handle<Object> structure,
uint32_t index,
@@ -3225,7 +3212,8 @@
public:
enum WeakObjectState {
NO_WEAK_OBJECTS,
- WEAK_OBJECTS_IN_OPTIMIZED_CODE
+ WEAK_OBJECTS_IN_OPTIMIZED_CODE,
+ WEAK_OBJECTS_IN_IC
};
// Getters for the field storing the first index for different type entries.
@@ -3347,23 +3335,6 @@
// [2 + number of descriptors * kDescriptorSize]: start of slack
class DescriptorArray: public FixedArray {
public:
- // WhitenessWitness is used to prove that a descriptor array is white
- // (unmarked), so incremental write barriers can be skipped because the
- // marking invariant cannot be broken and slots pointing into evacuation
- // candidates will be discovered when the object is scanned. A witness is
- // always stack-allocated right after creating an array. By allocating a
- // witness, incremental marking is globally disabled. The witness is then
- // passed along wherever needed to statically prove that the array is known to
- // be white.
- class WhitenessWitness {
- public:
- inline explicit WhitenessWitness(FixedArray* array);
- inline ~WhitenessWitness();
-
- private:
- IncrementalMarking* marking_;
- };
-
// Returns true for both shared empty_descriptor_array and for smis, which the
// map uses to encode additional bit fields when the descriptor array is not
// yet used.
@@ -3453,15 +3424,12 @@
// Accessor for complete descriptor.
inline void Get(int descriptor_number, Descriptor* desc);
- inline void Set(int descriptor_number,
- Descriptor* desc,
- const WhitenessWitness&);
+ inline void Set(int descriptor_number, Descriptor* desc);
void Replace(int descriptor_number, Descriptor* descriptor);
// Append automatically sets the enumeration index. This should only be used
// to add descriptors in bulk at the end, followed by sorting the descriptor
// array.
- inline void Append(Descriptor* desc, const WhitenessWitness&);
inline void Append(Descriptor* desc);
static Handle<DescriptorArray> Merge(Handle<Map> left_map,
@@ -3500,9 +3468,9 @@
// Allocates a DescriptorArray, but returns the singleton
// empty descriptor array object if number_of_descriptors is 0.
- MUST_USE_RESULT static MaybeObject* Allocate(Isolate* isolate,
- int number_of_descriptors,
- int slack = 0);
+ static Handle<DescriptorArray> Allocate(Isolate* isolate,
+ int number_of_descriptors,
+ int slack = 0);
// Casting.
static inline DescriptorArray* cast(Object* obj);
@@ -3556,6 +3524,23 @@
}
private:
+ // WhitenessWitness is used to prove that a descriptor array is white
+ // (unmarked), so incremental write barriers can be skipped because the
+ // marking invariant cannot be broken and slots pointing into evacuation
+ // candidates will be discovered when the object is scanned. A witness is
+ // always stack-allocated right after creating an array. By allocating a
+ // witness, incremental marking is globally disabled. The witness is then
+ // passed along wherever needed to statically prove that the array is known to
+ // be white.
+ class WhitenessWitness {
+ public:
+ inline explicit WhitenessWitness(DescriptorArray* array);
+ inline ~WhitenessWitness();
+
+ private:
+ IncrementalMarking* marking_;
+ };
+
// An entry in a DescriptorArray, represented as an (array, index) pair.
class Entry {
public:
@@ -3595,7 +3580,11 @@
DescriptorArray* src,
const WhitenessWitness&);
- inline void Set(int descriptor_number, Descriptor* desc);
+ inline void Set(int descriptor_number,
+ Descriptor* desc,
+ const WhitenessWitness&);
+
+ inline void Append(Descriptor* desc, const WhitenessWitness&);
// Swap first and second descriptor.
inline void SwapSortedKeys(int first, int second);
@@ -4097,11 +4086,6 @@
static void DoGenerateNewEnumerationIndices(
Handle<NameDictionary> dictionary);
- // For transforming properties of a JSObject.
- MUST_USE_RESULT MaybeObject* TransformPropertiesToFastFor(
- JSObject* obj,
- int unused_property_fields);
-
// Find entry for key, otherwise return kNotFound. Optimized version of
// HashTable::FindEntry.
int FindEntry(Name* key);
@@ -5494,6 +5478,17 @@
inline bool is_to_boolean_ic_stub() { return kind() == TO_BOOLEAN_IC; }
inline bool is_keyed_stub();
inline bool is_optimized_code() { return kind() == OPTIMIZED_FUNCTION; }
+ inline bool is_weak_stub();
+ inline void mark_as_weak_stub();
+ inline bool is_invalidated_weak_stub();
+ inline void mark_as_invalidated_weak_stub();
+
+ inline bool CanBeWeakStub() {
+ Kind k = kind();
+ return (k == LOAD_IC || k == STORE_IC || k == KEYED_LOAD_IC ||
+ k == KEYED_STORE_IC || k == COMPARE_NIL_IC) &&
+ ic_state() == MONOMORPHIC;
+ }
inline void set_raw_kind_specific_flags1(int value);
inline void set_raw_kind_specific_flags2(int value);
@@ -5751,11 +5746,17 @@
void VerifyEmbeddedObjectsDependency();
#endif
+ inline bool CanContainWeakObjects() {
+ return is_optimized_code() || is_weak_stub();
+ }
+
inline bool IsWeakObject(Object* object) {
- return is_optimized_code() && IsWeakObjectInOptimizedCode(object);
+ return (is_optimized_code() && IsWeakObjectInOptimizedCode(object)) ||
+ (is_weak_stub() && IsWeakObjectInIC(object));
}
static inline bool IsWeakObjectInOptimizedCode(Object* object);
+ static inline bool IsWeakObjectInIC(Object* object);
// Max loop nesting marker used to postpose OSR. We don't take loop
// nesting that is deeper than 5 levels into account.
@@ -5818,11 +5819,17 @@
static const int kMarkedForDeoptimizationFirstBit =
kStackSlotsFirstBit + kStackSlotsBitCount + 1;
static const int kMarkedForDeoptimizationBitCount = 1;
+ static const int kWeakStubFirstBit =
+ kMarkedForDeoptimizationFirstBit + kMarkedForDeoptimizationBitCount;
+ static const int kWeakStubBitCount = 1;
+ static const int kInvalidatedWeakStubFirstBit =
+ kWeakStubFirstBit + kWeakStubBitCount;
+ static const int kInvalidatedWeakStubBitCount = 1;
STATIC_ASSERT(kStackSlotsFirstBit + kStackSlotsBitCount <= 32);
STATIC_ASSERT(kHasFunctionCacheFirstBit + kHasFunctionCacheBitCount <= 32);
- STATIC_ASSERT(kMarkedForDeoptimizationFirstBit +
- kMarkedForDeoptimizationBitCount <= 32);
+ STATIC_ASSERT(kInvalidatedWeakStubFirstBit +
+ kInvalidatedWeakStubBitCount <= 32);
class StackSlotsField: public BitField<int,
kStackSlotsFirstBit, kStackSlotsBitCount> {}; // NOLINT
@@ -5831,6 +5838,12 @@
class MarkedForDeoptimizationField: public BitField<bool,
kMarkedForDeoptimizationFirstBit,
kMarkedForDeoptimizationBitCount> {}; // NOLINT
+ class WeakStubField: public BitField<bool,
+ kWeakStubFirstBit,
+ kWeakStubBitCount> {}; // NOLINT
+ class InvalidatedWeakStubField: public BitField<bool,
+ kInvalidatedWeakStubFirstBit,
+ kInvalidatedWeakStubBitCount> {}; // NOLINT
// KindSpecificFlags2 layout (ALL)
static const int kIsCrankshaftedBit = 0;
@@ -5915,9 +5928,14 @@
class DependentCode: public FixedArray {
public:
enum DependencyGroup {
+ // Group of IC stubs that weakly embed this map and depend on being
+ // invalidated when the map is garbage collected. Dependent IC stubs form
+ // a linked list. This group stores only the head of the list. This means
+ // that the number_of_entries(kWeakICGroup) is 0 or 1.
+ kWeakICGroup,
// Group of code that weakly embed this map and depend on being
// deoptimized when the map is garbage collected.
- kWeaklyEmbeddedGroup,
+ kWeakCodeGroup,
// Group of code that embed a transition to this map, and depend on being
// deoptimized when the transition is replaced by a new version.
kTransitionGroup,
@@ -5968,6 +5986,7 @@
bool MarkCodeForDeoptimization(Isolate* isolate,
DependentCode::DependencyGroup group);
+ void AddToDependentICList(Handle<Code> stub);
// The following low-level accessors should only be used by this class
// and the mark compact collector.
@@ -6278,7 +6297,7 @@
// [stub cache]: contains stubs compiled for this map.
DECL_ACCESSORS(code_cache, Object)
- // [dependent code]: list of optimized codes that have this map embedded.
+ // [dependent code]: list of optimized codes that weakly embed this map.
DECL_ACCESSORS(dependent_code, DependentCode)
// [back pointer]: points back to the parent map from which a transition
@@ -6299,8 +6318,8 @@
// 2 + 2 * i: prototype
// 3 + 2 * i: target map
inline FixedArray* GetPrototypeTransitions();
- MUST_USE_RESULT inline MaybeObject* SetPrototypeTransitions(
- FixedArray* prototype_transitions);
+ static inline void SetPrototypeTransitions(
+ Handle<Map> map, Handle<FixedArray> prototype_transitions);
inline bool HasPrototypeTransitions();
static const int kProtoTransitionHeaderSize = 1;
@@ -6393,9 +6412,7 @@
static Handle<Map> CurrentMapForDeprecatedInternal(Handle<Map> map);
static Handle<Map> RawCopy(Handle<Map> map, int instance_size);
- MUST_USE_RESULT MaybeObject* RawCopy(int instance_size);
static Handle<Map> CopyDropDescriptors(Handle<Map> map);
- MUST_USE_RESULT MaybeObject* CopyDropDescriptors();
static Handle<Map> CopyReplaceDescriptors(
Handle<Map> map,
Handle<DescriptorArray> descriptors,
@@ -6439,8 +6456,7 @@
PropertyNormalizationMode mode,
NormalizedMapSharingMode sharing);
- inline void AppendDescriptor(Descriptor* desc,
- const DescriptorArray::WhitenessWitness&);
+ inline void AppendDescriptor(Descriptor* desc);
// Returns a copy of the map, with all transitions dropped from the
// instance descriptors.
@@ -6466,9 +6482,6 @@
// Casting.
static inline Map* cast(Object* obj);
- // Locate an accessor in the instance descriptor.
- AccessorDescriptor* FindAccessor(Name* name);
-
// Code cache operations.
// Clears the code cache.
@@ -6566,6 +6579,7 @@
void AddDependentCode(DependentCode::DependencyGroup group,
Handle<Code> code);
+ void AddDependentIC(Handle<Code> stub);
bool IsMapInArrayPrototypeChain();
@@ -7774,14 +7788,6 @@
// Retrieve the property cell used to store a property.
PropertyCell* GetPropertyCell(LookupResult* result);
- // This is like GetProperty, but is used when you know the lookup won't fail
- // by throwing an exception. This is for the debug and builtins global
- // objects, where it is known which properties can be expected to be present
- // on the object.
- static inline Handle<Object> GetPropertyNoExceptionThrown(
- Handle<GlobalObject> global,
- Handle<Name> name);
-
// Casting.
static inline GlobalObject* cast(Object* obj);
@@ -8791,6 +8797,7 @@
// Equality operations.
inline bool Equals(Name* other);
+ inline static bool Equals(Handle<Name> one, Handle<Name> two);
// Conversion.
inline bool AsArrayIndex(uint32_t* index);
@@ -8927,28 +8934,37 @@
// true.
Vector<const uint8_t> ToOneByteVector() {
ASSERT_EQ(ASCII, state_);
- return buffer_;
+ return Vector<const uint8_t>(onebyte_start, length_);
}
// Return the two-byte content of the string. Only use if IsTwoByte()
// returns true.
Vector<const uc16> ToUC16Vector() {
ASSERT_EQ(TWO_BYTE, state_);
- return Vector<const uc16>::cast(buffer_);
+ return Vector<const uc16>(twobyte_start, length_);
+ }
+
+ uc16 Get(int i) {
+ ASSERT(i < length_);
+ ASSERT(state_ != NON_FLAT);
+ if (state_ == ASCII) return onebyte_start[i];
+ return twobyte_start[i];
}
private:
enum State { NON_FLAT, ASCII, TWO_BYTE };
// Constructors only used by String::GetFlatContent().
- explicit FlatContent(Vector<const uint8_t> chars)
- : buffer_(chars),
- state_(ASCII) { }
- explicit FlatContent(Vector<const uc16> chars)
- : buffer_(Vector<const byte>::cast(chars)),
- state_(TWO_BYTE) { }
- FlatContent() : buffer_(), state_(NON_FLAT) { }
+ explicit FlatContent(const uint8_t* start, int length)
+ : onebyte_start(start), length_(length), state_(ASCII) { }
+ explicit FlatContent(const uc16* start, int length)
+ : twobyte_start(start), length_(length), state_(TWO_BYTE) { }
+ FlatContent() : onebyte_start(NULL), length_(0), state_(NON_FLAT) { }
- Vector<const uint8_t> buffer_;
+ union {
+ const uint8_t* onebyte_start;
+ const uc16* twobyte_start;
+ };
+ int length_;
State state_;
friend class String;
@@ -8986,7 +9002,7 @@
// to this method are not efficient unless the string is flat.
INLINE(uint16_t Get(int index));
- // Try to flatten the string. Checks first inline to see if it is
+ // Flattens the string. Checks first inline to see if it is
// necessary. Does nothing if the string is not a cons string.
// Flattening allocates a sequential string with the same data as
// the given string and mutates the cons string to a degenerate
@@ -8998,23 +9014,10 @@
//
// Degenerate cons strings are handled specially by the garbage
// collector (see IsShortcutCandidate).
- //
- // Use FlattenString from Handles.cc to flatten even in case an
- // allocation failure happens.
- inline MaybeObject* TryFlatten(PretenureFlag pretenure = NOT_TENURED);
-
- // Convenience function. Has exactly the same behavior as
- // TryFlatten(), except in the case of failure returns the original
- // string.
- inline String* TryFlattenGetString(PretenureFlag pretenure = NOT_TENURED);
static inline Handle<String> Flatten(Handle<String> string,
PretenureFlag pretenure = NOT_TENURED);
- static Handle<String> SlowFlatten(Handle<ConsString> cons,
- PretenureFlag tenure);
-
-
// Tries to return the content of a flat string as a structure holding either
// a flat vector of char or of uc16.
// If the string isn't flat, and therefore doesn't have flat content, the
@@ -9032,6 +9035,7 @@
// String equality operations.
inline bool Equals(String* other);
+ inline static bool Equals(Handle<String> one, Handle<String> two);
bool IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match = false);
bool IsOneByteEqualTo(Vector<const uint8_t> str);
bool IsTwoByteEqualTo(Vector<const uc16> str);
@@ -9202,15 +9206,15 @@
private:
friend class Name;
- // Try to flatten the top level ConsString that is hiding behind this
- // string. This is a no-op unless the string is a ConsString. Flatten
- // mutates the ConsString and might return a failure.
- MUST_USE_RESULT MaybeObject* SlowTryFlatten(PretenureFlag pretenure);
+ static Handle<String> SlowFlatten(Handle<ConsString> cons,
+ PretenureFlag tenure);
// Slow case of String::Equals. This implementation works on any strings
// but it is most efficient on strings that are almost flat.
bool SlowEquals(String* other);
+ static bool SlowEquals(Handle<String> one, Handle<String> two);
+
// Slow case of AsArrayIndex.
bool SlowAsArrayIndex(uint32_t* index);
@@ -9812,11 +9816,13 @@
// Casting.
static inline JSProxy* cast(Object* obj);
- MUST_USE_RESULT MaybeObject* GetPropertyWithHandler(
- Object* receiver,
- Name* name);
- MUST_USE_RESULT MaybeObject* GetElementWithHandler(
- Object* receiver,
+ MUST_USE_RESULT static MaybeHandle<Object> GetPropertyWithHandler(
+ Handle<JSProxy> proxy,
+ Handle<Object> receiver,
+ Handle<Name> name);
+ MUST_USE_RESULT static inline MaybeHandle<Object> GetElementWithHandler(
+ Handle<JSProxy> proxy,
+ Handle<Object> receiver,
uint32_t index);
// If the handler defines an accessor property with a setter, invoke it.
@@ -9887,7 +9893,7 @@
Handle<Object> value,
PropertyAttributes attributes,
StrictMode strict_mode);
- MUST_USE_RESULT static MaybeHandle<Object> SetElementWithHandler(
+ MUST_USE_RESULT static inline MaybeHandle<Object> SetElementWithHandler(
Handle<JSProxy> proxy,
Handle<JSReceiver> receiver,
uint32_t index,
@@ -9895,7 +9901,8 @@
StrictMode strict_mode);
static bool HasPropertyWithHandler(Handle<JSProxy> proxy, Handle<Name> name);
- static bool HasElementWithHandler(Handle<JSProxy> proxy, uint32_t index);
+ static inline bool HasElementWithHandler(Handle<JSProxy> proxy,
+ uint32_t index);
MUST_USE_RESULT static MaybeHandle<Object> DeletePropertyWithHandler(
Handle<JSProxy> proxy,
diff --git a/src/parser.cc b/src/parser.cc
index a738634..30c2c63 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -224,7 +224,33 @@
}
-FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) {
+ScriptData* ScriptData::New(const char* data, int length) {
+ // The length is obviously invalid.
+ if (length % sizeof(unsigned) != 0) {
+ return new ScriptData();
+ }
+
+ int deserialized_data_length = length / sizeof(unsigned);
+ unsigned* deserialized_data;
+ ScriptData* script_data = new ScriptData();
+ script_data->owns_store_ =
+ reinterpret_cast<intptr_t>(data) % sizeof(unsigned) != 0;
+ if (script_data->owns_store_) {
+ // Copy the data to align it.
+ deserialized_data = i::NewArray<unsigned>(deserialized_data_length);
+ i::CopyBytes(reinterpret_cast<char*>(deserialized_data),
+ data, static_cast<size_t>(length));
+ } else {
+ // If aligned, don't create a copy of the data.
+ deserialized_data = reinterpret_cast<unsigned*>(const_cast<char*>(data));
+ }
+ script_data->store_ =
+ Vector<unsigned>(deserialized_data, deserialized_data_length);
+ return script_data;
+}
+
+
+FunctionEntry ScriptData::GetFunctionEntry(int start) {
// The current pre-data entry must be a FunctionEntry with the given
// start position.
if ((function_index_ + FunctionEntry::kSize <= store_.length())
@@ -238,12 +264,12 @@
}
-int ScriptDataImpl::GetSymbolIdentifier() {
+int ScriptData::GetSymbolIdentifier() {
return ReadNumber(&symbol_data_);
}
-bool ScriptDataImpl::SanityCheck() {
+bool ScriptData::SanityCheck() {
// Check that the header data is valid and doesn't specify
// point to positions outside the store.
if (store_.length() < PreparseDataConstants::kHeaderSize) return false;
@@ -292,7 +318,7 @@
-const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) {
+const char* ScriptData::ReadString(unsigned* start, int* chars) {
int length = start[0];
char* result = NewArray<char>(length + 1);
for (int i = 0; i < length; i++) {
@@ -304,25 +330,25 @@
}
-Scanner::Location ScriptDataImpl::MessageLocation() const {
+Scanner::Location ScriptData::MessageLocation() const {
int beg_pos = Read(PreparseDataConstants::kMessageStartPos);
int end_pos = Read(PreparseDataConstants::kMessageEndPos);
return Scanner::Location(beg_pos, end_pos);
}
-bool ScriptDataImpl::IsReferenceError() const {
+bool ScriptData::IsReferenceError() const {
return Read(PreparseDataConstants::kIsReferenceErrorPos);
}
-const char* ScriptDataImpl::BuildMessage() const {
+const char* ScriptData::BuildMessage() const {
unsigned* start = ReadAddress(PreparseDataConstants::kMessageTextPos);
return ReadString(start, NULL);
}
-Vector<const char*> ScriptDataImpl::BuildArgs() const {
+Vector<const char*> ScriptData::BuildArgs() const {
int arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
const char** array = NewArray<const char*>(arg_count);
// Position after text found by skipping past length field and
@@ -338,12 +364,12 @@
}
-unsigned ScriptDataImpl::Read(int position) const {
+unsigned ScriptData::Read(int position) const {
return store_[PreparseDataConstants::kHeaderSize + position];
}
-unsigned* ScriptDataImpl::ReadAddress(int position) const {
+unsigned* ScriptData::ReadAddress(int position) const {
return &store_[PreparseDataConstants::kHeaderSize + position];
}
@@ -890,7 +916,7 @@
}
if (cached_data_mode_ == PRODUCE_CACHED_DATA) {
Vector<unsigned> store = recorder.ExtractData();
- *cached_data_ = new ScriptDataImpl(store);
+ *cached_data_ = new ScriptData(store);
log_ = NULL;
}
return result;
@@ -1126,7 +1152,8 @@
// Check "use strict" directive (ES5 14.1).
if (strict_mode() == SLOPPY &&
- directive->Equals(isolate()->heap()->use_strict_string()) &&
+ String::Equals(isolate()->factory()->use_strict_string(),
+ directive) &&
token_loc.end_pos - token_loc.beg_pos ==
isolate()->heap()->use_strict_string()->length() + 2) {
// TODO(mstarzinger): Global strict eval calls, need their own scope
@@ -1195,8 +1222,8 @@
ExpressionStatement* estmt = stmt->AsExpressionStatement();
if (estmt != NULL &&
estmt->expression()->AsVariableProxy() != NULL &&
- estmt->expression()->AsVariableProxy()->name()->Equals(
- isolate()->heap()->module_string()) &&
+ String::Equals(isolate()->factory()->module_string(),
+ estmt->expression()->AsVariableProxy()->name()) &&
!scanner()->literal_contains_escapes()) {
return ParseModuleDeclaration(NULL, ok);
}
@@ -2393,8 +2420,8 @@
!scanner()->HasAnyLineTerminatorBeforeNext() &&
expr != NULL &&
expr->AsVariableProxy() != NULL &&
- expr->AsVariableProxy()->name()->Equals(
- isolate()->heap()->native_string()) &&
+ String::Equals(isolate()->factory()->native_string(),
+ expr->AsVariableProxy()->name()) &&
!scanner()->literal_contains_escapes()) {
return ParseNativeDeclaration(ok);
}
@@ -2405,8 +2432,8 @@
peek() != Token::IDENTIFIER ||
scanner()->HasAnyLineTerminatorBeforeNext() ||
expr->AsVariableProxy() == NULL ||
- !expr->AsVariableProxy()->name()->Equals(
- isolate()->heap()->module_string()) ||
+ !String::Equals(isolate()->factory()->module_string(),
+ expr->AsVariableProxy()->name()) ||
scanner()->literal_contains_escapes()) {
ExpectSemicolon(CHECK_OK);
}
@@ -4536,27 +4563,27 @@
// ----------------------------------------------------------------------------
// The Parser interface.
-ScriptDataImpl::~ScriptDataImpl() {
+ScriptData::~ScriptData() {
if (owns_store_) store_.Dispose();
}
-int ScriptDataImpl::Length() {
+int ScriptData::Length() {
return store_.length() * sizeof(unsigned);
}
-const char* ScriptDataImpl::Data() {
+const char* ScriptData::Data() {
return reinterpret_cast<const char*>(store_.start());
}
-bool ScriptDataImpl::HasError() {
+bool ScriptData::HasError() {
return has_error();
}
-void ScriptDataImpl::Initialize() {
+void ScriptData::Initialize() {
// Prepares state for use.
if (store_.length() >= PreparseDataConstants::kHeaderSize) {
function_index_ = PreparseDataConstants::kHeaderSize;
@@ -4573,7 +4600,7 @@
}
-int ScriptDataImpl::ReadNumber(byte** source) {
+int ScriptData::ReadNumber(byte** source) {
// Reads a number from symbol_data_ in base 128. The most significant
// bit marks that there are more digits.
// If the first byte is 0x80 (kNumberTerminator), it would normally
@@ -4600,33 +4627,6 @@
}
-// Create a Scanner for the preparser to use as input, and preparse the source.
-ScriptDataImpl* PreParserApi::PreParse(Isolate* isolate,
- Utf16CharacterStream* source) {
- CompleteParserRecorder recorder;
- HistogramTimerScope timer(isolate->counters()->pre_parse());
- Scanner scanner(isolate->unicode_cache());
- intptr_t stack_limit = isolate->stack_guard()->real_climit();
- PreParser preparser(&scanner, &recorder, stack_limit);
- preparser.set_allow_lazy(true);
- preparser.set_allow_generators(FLAG_harmony_generators);
- preparser.set_allow_for_of(FLAG_harmony_iteration);
- preparser.set_allow_harmony_scoping(FLAG_harmony_scoping);
- preparser.set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals);
- scanner.Initialize(source);
- PreParser::PreParseResult result = preparser.PreParseProgram();
- if (result == PreParser::kPreParseStackOverflow) {
- isolate->StackOverflow();
- return NULL;
- }
-
- // Extract the accumulated data from the recorder as a single
- // contiguous vector that we are responsible for disposing.
- Vector<unsigned> store = recorder.ExtractData();
- return new ScriptDataImpl(store);
-}
-
-
bool RegExpParser::ParseRegExp(FlatStringReader* input,
bool multiline,
RegExpCompileData* result,
@@ -4664,7 +4664,7 @@
SetCachedData(info()->cached_data(), info()->cached_data_mode());
if (info()->cached_data_mode() == CONSUME_CACHED_DATA &&
(*info()->cached_data())->has_error()) {
- ScriptDataImpl* cached_data = *(info()->cached_data());
+ ScriptData* cached_data = *(info()->cached_data());
Scanner::Location loc = cached_data->MessageLocation();
const char* message = cached_data->BuildMessage();
Vector<const char*> args = cached_data->BuildArgs();
diff --git a/src/parser.h b/src/parser.h
index cb13f71..7186f63 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -82,17 +82,22 @@
};
-class ScriptDataImpl : public ScriptData {
+class ScriptData {
public:
- explicit ScriptDataImpl(Vector<unsigned> store)
+ explicit ScriptData(Vector<unsigned> store)
: store_(store),
owns_store_(true) { }
- // Create an empty ScriptDataImpl that is guaranteed to not satisfy
+ // Create an empty ScriptData that is guaranteed to not satisfy
// a SanityCheck.
- ScriptDataImpl() : owns_store_(false) { }
+ ScriptData() : owns_store_(false) { }
- virtual ~ScriptDataImpl();
+ // The created ScriptData won't take ownership of the data. If the alignment
+ // is not correct, this will copy the data (and the created ScriptData will
+ // take ownership of the copy).
+ static ScriptData* New(const char* data, int length);
+
+ virtual ~ScriptData();
virtual int Length();
virtual const char* Data();
virtual bool HasError();
@@ -128,6 +133,10 @@
unsigned version() { return store_[PreparseDataConstants::kVersionOffset]; }
private:
+ // Disable copying and assigning; because of owns_store they won't be correct.
+ ScriptData(const ScriptData&);
+ ScriptData& operator=(const ScriptData&);
+
friend class v8::ScriptCompiler;
Vector<unsigned> store_;
unsigned char* symbol_data_;
@@ -140,30 +149,8 @@
// Reads a number from the current symbols
int ReadNumber(byte** source);
- ScriptDataImpl(const char* backing_store, int length)
- : store_(reinterpret_cast<unsigned*>(const_cast<char*>(backing_store)),
- length / static_cast<int>(sizeof(unsigned))),
- owns_store_(false) {
- ASSERT_EQ(0, static_cast<int>(
- reinterpret_cast<intptr_t>(backing_store) % sizeof(unsigned)));
- }
-
// Read strings written by ParserRecorder::WriteString.
static const char* ReadString(unsigned* start, int* chars);
-
- friend class ScriptData;
-};
-
-
-class PreParserApi {
- public:
- // Pre-parse a character stream and return full preparse data.
- //
- // This interface is here instead of in preparser.h because it instantiates a
- // preparser recorder object that is suited to the parser's purposes. Also,
- // the preparser doesn't know about ScriptDataImpl.
- static ScriptDataImpl* PreParse(Isolate* isolate,
- Utf16CharacterStream* source);
};
@@ -682,7 +669,7 @@
// Report syntax error
void ReportInvalidPreparseData(Handle<String> name, bool* ok);
- void SetCachedData(ScriptDataImpl** data,
+ void SetCachedData(ScriptData** data,
CachedDataMode cached_data_mode) {
cached_data_mode_ = cached_data_mode;
if (cached_data_mode == NO_CACHED_DATA) {
@@ -695,7 +682,7 @@
}
bool inside_with() const { return scope_->inside_with(); }
- ScriptDataImpl** cached_data() const { return cached_data_; }
+ ScriptData** cached_data() const { return cached_data_; }
CachedDataMode cached_data_mode() const { return cached_data_mode_; }
Scope* DeclarationScope(VariableMode mode) {
return IsLexicalVariableMode(mode)
@@ -814,7 +801,7 @@
PreParser* reusable_preparser_;
Scope* original_scope_; // for ES5 function declarations in sloppy eval
Target* target_stack_; // for break, continue statements
- ScriptDataImpl** cached_data_;
+ ScriptData** cached_data_;
CachedDataMode cached_data_mode_;
CompilationInfo* info_;
diff --git a/src/runtime.cc b/src/runtime.cc
index f2e2650..4f34085 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -1911,17 +1911,16 @@
};
-MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(
- Isolate* isolate,
- Handle<JSObject> obj,
- Handle<Name> name) {
+MUST_USE_RESULT static MaybeHandle<Object> GetOwnProperty(Isolate* isolate,
+ Handle<JSObject> obj,
+ Handle<Name> name) {
Heap* heap = isolate->heap();
Factory* factory = isolate->factory();
// Due to some WebKit tests, we want to make sure that we do not log
// more than one access failure here.
AccessCheckResult access_check_result =
CheckPropertyAccess(obj, name, v8::ACCESS_HAS);
- RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
switch (access_check_result) {
case ACCESS_FORBIDDEN: return factory->false_value();
case ACCESS_ALLOWED: break;
@@ -1930,7 +1929,7 @@
PropertyAttributes attrs = JSReceiver::GetLocalPropertyAttribute(obj, name);
if (attrs == ABSENT) {
- RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
+ RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
return factory->undefined_value();
}
ASSERT(!isolate->has_scheduled_exception());
@@ -2054,8 +2053,8 @@
CONVERT_SMI_ARG_CHECKED(index, 1)
int offset = index * kPointerSize + HeapObject::kHeaderSize;
InstanceType type = templ->map()->instance_type();
- RUNTIME_ASSERT(type == FUNCTION_TEMPLATE_INFO_TYPE ||
- type == OBJECT_TEMPLATE_INFO_TYPE);
+ RUNTIME_ASSERT(type == FUNCTION_TEMPLATE_INFO_TYPE ||
+ type == OBJECT_TEMPLATE_INFO_TYPE);
RUNTIME_ASSERT(offset > 0);
if (type == FUNCTION_TEMPLATE_INFO_TYPE) {
RUNTIME_ASSERT(offset < FunctionTemplateInfo::kSize);
@@ -2740,10 +2739,11 @@
CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
if (!callable->IsJSFunction()) {
HandleScope scope(isolate);
- bool threw = false;
- Handle<Object> delegate = Execution::TryGetFunctionDelegate(
- isolate, Handle<JSReceiver>(callable), &threw);
- if (threw) return Failure::Exception();
+ Handle<Object> delegate;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, delegate,
+ Execution::TryGetFunctionDelegate(
+ isolate, Handle<JSReceiver>(callable)));
callable = JSFunction::cast(*delegate);
}
JSFunction* function = JSFunction::cast(callable);
@@ -2759,10 +2759,11 @@
if (!callable->IsJSFunction()) {
HandleScope scope(isolate);
- bool threw = false;
- Handle<Object> delegate = Execution::TryGetFunctionDelegate(
- isolate, Handle<JSReceiver>(callable), &threw);
- if (threw) return Failure::Exception();
+ Handle<Object> delegate;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, delegate,
+ Execution::TryGetFunctionDelegate(
+ isolate, Handle<JSReceiver>(callable)));
callable = JSFunction::cast(*delegate);
}
JSFunction* function = JSFunction::cast(callable);
@@ -2797,14 +2798,10 @@
Handle<JSFunction>(
JSFunction::NativeContextFromLiterals(*literals)->regexp_function());
// Compute the regular expression literal.
- bool has_pending_exception;
- Handle<Object> regexp =
- RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags,
- &has_pending_exception);
- if (has_pending_exception) {
- ASSERT(isolate->has_pending_exception());
- return Failure::Exception();
- }
+ Handle<Object> regexp;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, regexp,
+ RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags));
literals->set(index, *regexp);
return *regexp;
}
@@ -4373,8 +4370,7 @@
if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
- int position =
- Runtime::StringMatch(isolate, sub, pat, start_index);
+ int position = Runtime::StringMatch(isolate, sub, pat, start_index);
return Smi::FromInt(position);
}
@@ -4474,13 +4470,13 @@
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLocaleCompare) {
- SealHandleScope shs(isolate);
+ HandleScope handle_scope(isolate);
ASSERT(args.length() == 2);
- CONVERT_ARG_CHECKED(String, str1, 0);
- CONVERT_ARG_CHECKED(String, str2, 1);
+ CONVERT_ARG_HANDLE_CHECKED(String, str1, 0);
+ CONVERT_ARG_HANDLE_CHECKED(String, str2, 1);
- if (str1 == str2) return Smi::FromInt(0); // Equal.
+ if (str1.is_identical_to(str2)) return Smi::FromInt(0); // Equal.
int str1_length = str1->length();
int str2_length = str2->length();
@@ -4500,21 +4496,17 @@
int d = str1->Get(0) - str2->Get(0);
if (d != 0) return Smi::FromInt(d);
- str1->TryFlatten();
- str2->TryFlatten();
+ str1 = String::Flatten(str1);
+ str2 = String::Flatten(str2);
- ConsStringIteratorOp* op1 =
- isolate->runtime_state()->string_locale_compare_it1();
- ConsStringIteratorOp* op2 =
- isolate->runtime_state()->string_locale_compare_it2();
- // TODO(dcarney) Can do array compares here more efficiently.
- StringCharacterStream stream1(str1, op1);
- StringCharacterStream stream2(str2, op2);
+ DisallowHeapAllocation no_gc;
+ String::FlatContent flat1 = str1->GetFlatContent();
+ String::FlatContent flat2 = str2->GetFlatContent();
for (int i = 0; i < end; i++) {
- uint16_t char1 = stream1.GetNext();
- uint16_t char2 = stream2.GetNext();
- if (char1 != char2) return Smi::FromInt(char1 - char2);
+ if (flat1.Get(i) != flat2.Get(i)) {
+ return Smi::FromInt(flat1.Get(i) - flat2.Get(i));
+ }
}
return Smi::FromInt(str1_length - str2_length);
@@ -4915,14 +4907,14 @@
}
-static Handle<Name> ToName(Isolate* isolate, Handle<Object> key) {
+MUST_USE_RESULT
+static MaybeHandle<Name> ToName(Isolate* isolate, Handle<Object> key) {
if (key->IsName()) {
return Handle<Name>::cast(key);
} else {
- bool has_pending_exception = false;
- Handle<Object> converted =
- Execution::ToString(isolate, key, &has_pending_exception);
- if (has_pending_exception) return Handle<Name>();
+ Handle<Object> converted;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, converted, Execution::ToString(isolate, key), Name);
return Handle<Name>::cast(converted);
}
}
@@ -4938,8 +4930,8 @@
}
// Convert the key to a name - possibly by calling back into JavaScript.
- Handle<Name> name = ToName(isolate, key);
- RETURN_IF_EMPTY_HANDLE_VALUE(isolate, name, MaybeHandle<Object>());
+ Handle<Name> name;
+ ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object);
return isolate->factory()->ToBoolean(JSReceiver::HasProperty(object, name));
}
@@ -4950,9 +4942,9 @@
Handle<Object> key) {
if (object->IsUndefined() || object->IsNull()) {
Handle<Object> args[2] = { key, object };
- isolate->Throw(*isolate->factory()->NewTypeError("non_object_property_load",
- HandleVector(args, 2)));
- return Handle<Object>();
+ return isolate->Throw<Object>(
+ isolate->factory()->NewTypeError("non_object_property_load",
+ HandleVector(args, 2)));
}
// Check if the given key is an array index.
@@ -4962,8 +4954,8 @@
}
// Convert the key to a name - possibly by calling back into JavaScript.
- Handle<Name> name = ToName(isolate, key);
- RETURN_IF_EMPTY_HANDLE_VALUE(isolate, name, Handle<Object>());
+ Handle<Name> name;
+ ASSIGN_RETURN_ON_EXCEPTION(isolate, name, ToName(isolate, key), Object);
// Check if the name is trivially convertible to an index and get
// the element if so.
@@ -5209,31 +5201,11 @@
// Return property without being observable by accessors or interceptors.
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDataProperty) {
- SealHandleScope shs(isolate);
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
- LookupResult lookup(isolate);
- object->LookupRealNamedProperty(*key, &lookup);
- if (lookup.IsFound() && !lookup.IsTransition()) {
- switch (lookup.type()) {
- case NORMAL:
- return lookup.holder()->GetNormalizedProperty(&lookup);
- case FIELD:
- return lookup.holder()->FastPropertyAt(
- lookup.representation(),
- lookup.GetFieldIndex().field_index());
- case CONSTANT:
- return lookup.GetConstant();
- case CALLBACKS:
- case HANDLER:
- case INTERCEPTOR:
- break;
- case NONEXISTENT:
- UNREACHABLE();
- }
- }
- return isolate->heap()->undefined_value();
+ return *JSObject::GetDataProperty(object, key);
}
@@ -5255,10 +5227,13 @@
}
if (object->IsJSProxy()) {
- bool has_pending_exception = false;
- Handle<Object> name_object = key->IsSymbol()
- ? key : Execution::ToString(isolate, key, &has_pending_exception);
- if (has_pending_exception) return MaybeHandle<Object>(); // exception
+ Handle<Object> name_object;
+ if (key->IsSymbol()) {
+ name_object = key;
+ } else {
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, name_object, Execution::ToString(isolate, key), Object);
+ }
Handle<Name> name = Handle<Name>::cast(name_object);
return JSReceiver::SetProperty(Handle<JSProxy>::cast(object), name, value,
attr,
@@ -5288,11 +5263,8 @@
if (js_object->HasExternalArrayElements() ||
js_object->HasFixedTypedArrayElements()) {
if (!value->IsNumber() && !value->IsUndefined()) {
- bool has_exception;
- Handle<Object> number =
- Execution::ToNumber(isolate, value, &has_exception);
- if (has_exception) return MaybeHandle<Object>(); // exception
- value = number;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, value, Execution::ToNumber(isolate, value), Object);
}
}
@@ -5308,11 +5280,8 @@
if (name->AsArrayIndex(&index)) {
if (js_object->HasExternalArrayElements()) {
if (!value->IsNumber() && !value->IsUndefined()) {
- bool has_exception;
- Handle<Object> number =
- Execution::ToNumber(isolate, value, &has_exception);
- if (has_exception) return MaybeHandle<Object>(); // exception
- value = number;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, value, Execution::ToNumber(isolate, value), Object);
}
}
return JSObject::SetElement(js_object, index, value, attr,
@@ -5324,10 +5293,9 @@
}
// Call-back into JavaScript to convert the key to a string.
- bool has_pending_exception = false;
- Handle<Object> converted =
- Execution::ToString(isolate, key, &has_pending_exception);
- if (has_pending_exception) return MaybeHandle<Object>(); // exception
+ Handle<Object> converted;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, converted, Execution::ToString(isolate, key), Object);
Handle<String> name = Handle<String>::cast(converted);
if (name->AsArrayIndex(&index)) {
@@ -5375,10 +5343,9 @@
}
// Call-back into JavaScript to convert the key to a string.
- bool has_pending_exception = false;
- Handle<Object> converted =
- Execution::ToString(isolate, key, &has_pending_exception);
- if (has_pending_exception) return MaybeHandle<Object>(); // exception
+ Handle<Object> converted;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, converted, Execution::ToString(isolate, key), Object);
Handle<String> name = Handle<String>::cast(converted);
if (name->AsArrayIndex(&index)) {
@@ -5416,10 +5383,9 @@
name = Handle<Name>::cast(key);
} else {
// Call-back into JavaScript to convert the key to a string.
- bool has_pending_exception = false;
- Handle<Object> converted = Execution::ToString(
- isolate, key, &has_pending_exception);
- if (has_pending_exception) return MaybeHandle<Object>();
+ Handle<Object> converted;
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, converted, Execution::ToString(isolate, key), Object);
name = Handle<String>::cast(converted);
}
@@ -5758,8 +5724,12 @@
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
Handle<JSArray> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, GetKeysFor(object));
- return *result;
+
+ isolate->counters()->for_in()->Increment();
+ Handle<FixedArray> elements;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, elements, GetKeysInFixedArrayFor(object, INCLUDE_PROTOS));
+ return *isolate->factory()->NewJSArrayWithElements(elements);
}
@@ -6057,17 +6027,18 @@
HandleScope scope(isolate);
if (args[0]->IsSymbol()) {
// Lookup in the initial Object.prototype object.
- Handle<Object> result = Object::GetProperty(
- isolate->initial_object_prototype(), args.at<Symbol>(0));
- RETURN_IF_EMPTY_HANDLE(isolate, result);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ Object::GetProperty(
+ isolate->initial_object_prototype(), args.at<Symbol>(0)));
return *result;
}
// Convert the key to a string.
- bool exception = false;
- Handle<Object> converted =
- Execution::ToString(isolate, args.at<Object>(0), &exception);
- if (exception) return Failure::Exception();
+ Handle<Object> converted;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, converted, Execution::ToString(isolate, args.at<Object>(0)));
Handle<String> key = Handle<String>::cast(converted);
// Try to convert the string key into an array index.
@@ -6085,8 +6056,10 @@
}
// Handle special arguments properties.
- if (key->Equals(isolate->heap()->length_string())) return Smi::FromInt(n);
- if (key->Equals(isolate->heap()->callee_string())) {
+ if (String::Equals(isolate->factory()->length_string(), key)) {
+ return Smi::FromInt(n);
+ }
+ if (String::Equals(isolate->factory()->callee_string(), key)) {
JSFunction* function = frame->function();
if (function->shared()->strict_mode() == STRICT) {
return isolate->Throw(*isolate->factory()->NewTypeError(
@@ -6096,9 +6069,10 @@
}
// Lookup in the initial Object.prototype object.
- Handle<Object> result = Object::GetProperty(
- isolate->initial_object_prototype(), key);
- RETURN_IF_EMPTY_HANDLE(isolate, result);
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ Object::GetProperty(isolate->initial_object_prototype(), key));
return *result;
}
@@ -6189,17 +6163,18 @@
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) {
- SealHandleScope shs(isolate);
+ HandleScope handle_scope(isolate);
ASSERT(args.length() == 1);
- CONVERT_ARG_CHECKED(String, subject, 0);
- subject->TryFlatten();
+ CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
+ subject = String::Flatten(subject);
// Fast case: short integer or some sorts of junk values.
- int len = subject->length();
if (subject->IsSeqOneByteString()) {
+ int len = subject->length();
if (len == 0) return Smi::FromInt(0);
- uint8_t const* data = SeqOneByteString::cast(subject)->GetChars();
+ DisallowHeapAllocation no_gc;
+ uint8_t const* data = Handle<SeqOneByteString>::cast(subject)->GetChars();
bool minus = (data[0] == '-');
int start_pos = (minus ? 1 : 0);
@@ -6207,15 +6182,15 @@
return isolate->heap()->nan_value();
} else if (data[start_pos] > '9') {
// Fast check for a junk value. A valid string may start from a
- // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit or
- // the 'I' character ('Infinity'). All of that have codes not greater than
- // '9' except 'I' and .
+ // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit
+ // or the 'I' character ('Infinity'). All of that have codes not greater
+ // than '9' except 'I' and .
if (data[start_pos] != 'I' && data[start_pos] != 0xa0) {
return isolate->heap()->nan_value();
}
} else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
- // The maximal/minimal smi has 10 digits. If the string has less digits we
- // know it will fit into the smi-data type.
+ // The maximal/minimal smi has 10 digits. If the string has less digits
+ // we know it will fit into the smi-data type.
int d = ParseDecimalInteger(data, start_pos, len);
if (minus) {
if (d == 0) return isolate->heap()->minus_zero_value();
@@ -6244,8 +6219,9 @@
// Type", https://bugs.ecmascript.org/show_bug.cgi?id=1584
flags |= ALLOW_OCTAL | ALLOW_BINARY;
}
- return isolate->heap()->NumberFromDouble(
- StringToDouble(isolate->unicode_cache(), subject, flags));
+
+ return *isolate->factory()->NewNumber(StringToDouble(
+ isolate->unicode_cache(), *subject, flags));
}
@@ -6319,29 +6295,40 @@
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseInt) {
- SealHandleScope shs(isolate);
-
- CONVERT_ARG_CHECKED(String, s, 0);
+ HandleScope handle_scope(isolate);
+ CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
CONVERT_NUMBER_CHECKED(int, radix, Int32, args[1]);
-
- s->TryFlatten();
-
RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
- double value = StringToInt(isolate->unicode_cache(), s, radix);
- return isolate->heap()->NumberFromDouble(value);
+
+ subject = String::Flatten(subject);
+ double value;
+
+ { DisallowHeapAllocation no_gc;
+ String::FlatContent flat = subject->GetFlatContent();
+
+ // ECMA-262 section 15.1.2.3, empty string is NaN
+ if (flat.IsAscii()) {
+ value = StringToInt(
+ isolate->unicode_cache(), flat.ToOneByteVector(), radix);
+ } else {
+ value = StringToInt(
+ isolate->unicode_cache(), flat.ToUC16Vector(), radix);
+ }
+ }
+
+ return *isolate->factory()->NewNumber(value);
}
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseFloat) {
- SealHandleScope shs(isolate);
- CONVERT_ARG_CHECKED(String, str, 0);
+ HandleScope shs(isolate);
+ CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
- // ECMA-262 section 15.1.2.3, empty string is NaN
- double value = StringToDouble(isolate->unicode_cache(),
- str, ALLOW_TRAILING_JUNK, OS::nan_value());
+ subject = String::Flatten(subject);
+ double value = StringToDouble(
+ isolate->unicode_cache(), *subject, ALLOW_TRAILING_JUNK, OS::nan_value());
- // Create a number object from the value.
- return isolate->heap()->NumberFromDouble(value);
+ return *isolate->factory()->NewNumber(value);
}
@@ -7516,13 +7503,13 @@
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) {
- SealHandleScope shs(isolate);
+ HandleScope handle_scope(isolate);
ASSERT(args.length() == 2);
- CONVERT_ARG_CHECKED(String, x, 0);
- CONVERT_ARG_CHECKED(String, y, 1);
+ CONVERT_ARG_HANDLE_CHECKED(String, x, 0);
+ CONVERT_ARG_HANDLE_CHECKED(String, y, 1);
- bool not_equal = !x->Equals(y);
+ bool not_equal = !String::Equals(x, y);
// This is slightly convoluted because the value that signifies
// equality is 0 and inequality is 1 so we have to negate the result
// from String::Equals.
@@ -7623,27 +7610,33 @@
}
-static Object* StringCharacterStreamCompare(RuntimeState* state,
- String* x,
- String* y) {
- StringCharacterStream stream_x(x, state->string_iterator_compare_x());
- StringCharacterStream stream_y(y, state->string_iterator_compare_y());
- while (stream_x.HasMore() && stream_y.HasMore()) {
- int d = stream_x.GetNext() - stream_y.GetNext();
- if (d < 0) return Smi::FromInt(LESS);
- else if (d > 0) return Smi::FromInt(GREATER);
+RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_StringCompare) {
+ HandleScope handle_scope(isolate);
+ ASSERT(args.length() == 2);
+
+ CONVERT_ARG_HANDLE_CHECKED(String, x, 0);
+ CONVERT_ARG_HANDLE_CHECKED(String, y, 1);
+
+ isolate->counters()->string_compare_runtime()->Increment();
+
+ // A few fast case tests before we flatten.
+ if (x.is_identical_to(y)) return Smi::FromInt(EQUAL);
+ if (y->length() == 0) {
+ if (x->length() == 0) return Smi::FromInt(EQUAL);
+ return Smi::FromInt(GREATER);
+ } else if (x->length() == 0) {
+ return Smi::FromInt(LESS);
}
- // x is (non-trivial) prefix of y:
- if (stream_y.HasMore()) return Smi::FromInt(LESS);
- // y is prefix of x:
- return Smi::FromInt(stream_x.HasMore() ? GREATER : EQUAL);
-}
+ int d = x->Get(0) - y->Get(0);
+ if (d < 0) return Smi::FromInt(LESS);
+ else if (d > 0) return Smi::FromInt(GREATER);
+ // Slow case.
+ x = String::Flatten(x);
+ y = String::Flatten(y);
-static Object* FlatStringCompare(String* x, String* y) {
- ASSERT(x->IsFlat());
- ASSERT(y->IsFlat());
+ DisallowHeapAllocation no_gc;
Object* equal_prefix_result = Smi::FromInt(EQUAL);
int prefix_length = x->length();
if (y->length() < prefix_length) {
@@ -7653,7 +7646,6 @@
equal_prefix_result = Smi::FromInt(LESS);
}
int r;
- DisallowHeapAllocation no_gc;
String::FlatContent x_content = x->GetFlatContent();
String::FlatContent y_content = y->GetFlatContent();
if (x_content.IsAscii()) {
@@ -7681,47 +7673,10 @@
} else {
result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
}
- ASSERT(result ==
- StringCharacterStreamCompare(x->GetIsolate()->runtime_state(), x, y));
return result;
}
-RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_StringCompare) {
- HandleScope shs(isolate);
- ASSERT(args.length() == 2);
-
- CONVERT_ARG_CHECKED(String, x, 0);
- CONVERT_ARG_CHECKED(String, y, 1);
-
- isolate->counters()->string_compare_runtime()->Increment();
-
- // A few fast case tests before we flatten.
- if (x == y) return Smi::FromInt(EQUAL);
- if (y->length() == 0) {
- if (x->length() == 0) return Smi::FromInt(EQUAL);
- return Smi::FromInt(GREATER);
- } else if (x->length() == 0) {
- return Smi::FromInt(LESS);
- }
-
- int d = x->Get(0) - y->Get(0);
- if (d < 0) return Smi::FromInt(LESS);
- else if (d > 0) return Smi::FromInt(GREATER);
-
- Object* obj;
- { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(x);
- if (!maybe_obj->ToObject(&obj)) return maybe_obj;
- }
- { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(y);
- if (!maybe_obj->ToObject(&obj)) return maybe_obj;
- }
-
- return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
- : StringCharacterStreamCompare(isolate->runtime_state(), x, y);
-}
-
-
#define RUNTIME_UNARY_MATH(Name, name) \
RUNTIME_FUNCTION(MaybeObject*, Runtime_Math##Name) { \
SealHandleScope shs(isolate); \
@@ -8280,22 +8235,17 @@
}
if (!bound_function->IsJSFunction()) {
- bool exception_thrown;
- bound_function = Execution::TryGetConstructorDelegate(isolate,
- bound_function,
- &exception_thrown);
- if (exception_thrown) return Failure::Exception();
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, bound_function,
+ Execution::TryGetConstructorDelegate(isolate, bound_function));
}
ASSERT(bound_function->IsJSFunction());
- bool exception = false;
- Handle<Object> result =
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
Execution::New(Handle<JSFunction>::cast(bound_function),
- total_argc, param_data.get(), &exception);
- if (exception) {
- return Failure::Exception();
- }
- ASSERT(!result.is_null());
+ total_argc, param_data.get()));
return *result;
}
@@ -8905,13 +8855,12 @@
argv[i] = Handle<Object>(object, isolate);
}
- bool threw;
Handle<JSReceiver> hfun(fun);
Handle<Object> hreceiver(receiver, isolate);
- Handle<Object> result = Execution::Call(
- isolate, hfun, hreceiver, argc, argv, &threw, true);
-
- if (threw) return Failure::Exception();
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ Execution::Call(isolate, hfun, hreceiver, argc, argv, true));
return *result;
}
@@ -8944,11 +8893,10 @@
Object::GetElement(isolate, arguments, offset + i));
}
- bool threw;
- Handle<Object> result = Execution::Call(
- isolate, fun, receiver, argc, argv, &threw, true);
-
- if (threw) return Failure::Exception();
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ Execution::Call(isolate, fun, receiver, argc, argv, true));
return *result;
}
@@ -9343,9 +9291,11 @@
// No need to unhole the value here. This is taken care of by the
// GetProperty function.
- Handle<Object> value = Object::GetProperty(object, name);
- RETURN_IF_EMPTY_HANDLE_VALUE(
- isolate, value, MakePair(Failure::Exception(), NULL));
+ Handle<Object> value;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate, value,
+ Object::GetProperty(object, name),
+ MakePair(Failure::Exception(), NULL));
return MakePair(*value, *receiver_handle);
}
@@ -11596,7 +11546,7 @@
Handle<Object> new_value) {
for (int i = 0; i < scope_info->ContextLocalCount(); i++) {
Handle<String> next_name(scope_info->ContextLocalName(i));
- if (variable_name->Equals(*next_name)) {
+ if (String::Equals(variable_name, next_name)) {
VariableMode mode;
InitializationFlag init_flag;
int context_index =
@@ -11628,7 +11578,8 @@
// Parameters.
for (int i = 0; i < scope_info->ParameterCount(); ++i) {
- if (scope_info->ParameterName(i)->Equals(*variable_name)) {
+ HandleScope scope(isolate);
+ if (String::Equals(handle(scope_info->ParameterName(i)), variable_name)) {
frame->SetParameterValue(i, *new_value);
// Argument might be shadowed in heap context, don't stop here.
default_result = true;
@@ -11637,7 +11588,8 @@
// Stack locals.
for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
- if (scope_info->StackLocalName(i)->Equals(*variable_name)) {
+ HandleScope scope(isolate);
+ if (String::Equals(handle(scope_info->StackLocalName(i)), variable_name)) {
frame->SetExpression(i, *new_value);
return true;
}
@@ -11780,7 +11732,7 @@
Handle<Object> new_value) {
ASSERT(context->IsCatchContext());
Handle<String> name(String::cast(context->extension()));
- if (!name->Equals(*variable_name)) {
+ if (!String::Equals(name, variable_name)) {
return false;
}
context->set(Context::THROWN_OBJECT_INDEX, *new_value);
@@ -12890,11 +12842,10 @@
RelocInfo::kNoPosition);
RETURN_IF_EMPTY_HANDLE(isolate, eval_fun);
- bool pending_exception;
- Handle<Object> result = Execution::Call(
- isolate, eval_fun, receiver, 0, NULL, &pending_exception);
-
- if (pending_exception) return Failure::Exception();
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ Execution::Call(isolate, eval_fun, receiver, 0, NULL));
// Skip the global proxy as it has no properties and always delegates to the
// real global object.
@@ -13654,31 +13605,24 @@
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
CONVERT_BOOLEAN_ARG_CHECKED(without_debugger, 1);
- Handle<Object> result;
- bool pending_exception;
- {
- if (without_debugger) {
- result = Execution::Call(isolate,
- function,
- isolate->global_object(),
- 0,
- NULL,
- &pending_exception);
- } else {
- EnterDebugger enter_debugger(isolate);
- result = Execution::Call(isolate,
- function,
- isolate->global_object(),
- 0,
- NULL,
- &pending_exception);
- }
- }
- if (!pending_exception) {
- return *result;
+ MaybeHandle<Object> maybe_result;
+ if (without_debugger) {
+ maybe_result = Execution::Call(isolate,
+ function,
+ isolate->global_object(),
+ 0,
+ NULL);
} else {
- return Failure::Exception();
+ EnterDebugger enter_debugger(isolate);
+ maybe_result = Execution::Call(isolate,
+ function,
+ isolate->global_object(),
+ 0,
+ NULL);
}
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, maybe_result);
+ return *result;
}
@@ -14003,13 +13947,10 @@
I18N::GetTemplate(isolate);
// Create an empty object wrapper.
- bool has_pending_exception = false;
- Handle<JSObject> local_object = Execution::InstantiateObject(
- date_format_template, &has_pending_exception);
- if (has_pending_exception) {
- ASSERT(isolate->has_pending_exception());
- return Failure::Exception();
- }
+ Handle<JSObject> local_object;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, local_object,
+ Execution::InstantiateObject(date_format_template));
// Set date time formatter as internal field of the resulting JS object.
icu::SimpleDateFormat* date_format = DateFormat::InitializeDateTimeFormat(
@@ -14043,13 +13984,9 @@
CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 1);
- bool has_pending_exception = false;
- Handle<Object> value =
- Execution::ToNumber(isolate, date, &has_pending_exception);
- if (has_pending_exception) {
- ASSERT(isolate->has_pending_exception());
- return Failure::Exception();
- }
+ Handle<Object> value;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, value, Execution::ToNumber(isolate, date));
icu::SimpleDateFormat* date_format =
DateFormat::UnpackDateFormat(isolate, date_format_holder);
@@ -14083,14 +14020,11 @@
UDate date = date_format->parse(u_date, status);
if (U_FAILURE(status)) return isolate->heap()->undefined_value();
- bool has_pending_exception = false;
- Handle<JSDate> result = Handle<JSDate>::cast(
- Execution::NewDate(
- isolate, static_cast<double>(date), &has_pending_exception));
- if (has_pending_exception) {
- ASSERT(isolate->has_pending_exception());
- return Failure::Exception();
- }
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result,
+ Execution::NewDate(isolate, static_cast<double>(date)));
+ ASSERT(result->IsJSDate());
return *result;
}
@@ -14108,13 +14042,10 @@
I18N::GetTemplate(isolate);
// Create an empty object wrapper.
- bool has_pending_exception = false;
- Handle<JSObject> local_object = Execution::InstantiateObject(
- number_format_template, &has_pending_exception);
- if (has_pending_exception) {
- ASSERT(isolate->has_pending_exception());
- return Failure::Exception();
- }
+ Handle<JSObject> local_object;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, local_object,
+ Execution::InstantiateObject(number_format_template));
// Set number formatter as internal field of the resulting JS object.
icu::DecimalFormat* number_format = NumberFormat::InitializeNumberFormat(
@@ -14147,13 +14078,9 @@
CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, number, 1);
- bool has_pending_exception = false;
- Handle<Object> value = Execution::ToNumber(
- isolate, number, &has_pending_exception);
- if (has_pending_exception) {
- ASSERT(isolate->has_pending_exception());
- return Failure::Exception();
- }
+ Handle<Object> value;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, value, Execution::ToNumber(isolate, number));
icu::DecimalFormat* number_format =
NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
@@ -14220,13 +14147,9 @@
Handle<ObjectTemplateInfo> collator_template = I18N::GetTemplate(isolate);
// Create an empty object wrapper.
- bool has_pending_exception = false;
- Handle<JSObject> local_object = Execution::InstantiateObject(
- collator_template, &has_pending_exception);
- if (has_pending_exception) {
- ASSERT(isolate->has_pending_exception());
- return Failure::Exception();
- }
+ Handle<JSObject> local_object;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, local_object, Execution::InstantiateObject(collator_template));
// Set collator as internal field of the resulting JS object.
icu::Collator* collator = Collator::InitializeCollator(
@@ -14321,13 +14244,10 @@
I18N::GetTemplate2(isolate);
// Create an empty object wrapper.
- bool has_pending_exception = false;
- Handle<JSObject> local_object = Execution::InstantiateObject(
- break_iterator_template, &has_pending_exception);
- if (has_pending_exception) {
- ASSERT(isolate->has_pending_exception());
- return Failure::Exception();
- }
+ Handle<JSObject> local_object;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, local_object,
+ Execution::InstantiateObject(break_iterator_template));
// Set break iterator as internal field of the resulting JS object.
icu::BreakIterator* break_iterator = BreakIterator::InitializeBreakIterator(
@@ -14678,14 +14598,9 @@
isolate);
// This handle is nor shared, nor used later, so it's safe.
Handle<Object> argv[] = { key_handle };
- bool pending_exception;
- value = Execution::Call(isolate,
- factory,
- receiver,
- ARRAY_SIZE(argv),
- argv,
- &pending_exception);
- if (pending_exception) return Failure::Exception();
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, value,
+ Execution::Call(isolate, factory, receiver, ARRAY_SIZE(argv), argv));
}
#ifdef VERIFY_HEAP
@@ -14917,8 +14832,7 @@
RUNTIME_FUNCTION(MaybeObject*, Runtime_RunMicrotasks) {
HandleScope scope(isolate);
ASSERT(args.length() == 0);
- if (isolate->microtask_pending())
- Execution::RunMicrotasks(isolate);
+ if (isolate->microtask_pending()) Execution::RunMicrotasks(isolate);
return isolate->heap()->undefined_value();
}
diff --git a/src/scanner.cc b/src/scanner.cc
index 48bfd33..67211e0 100644
--- a/src/scanner.cc
+++ b/src/scanner.cc
@@ -1142,7 +1142,8 @@
double Scanner::DoubleValue() {
ASSERT(is_literal_one_byte());
return StringToDouble(
- unicode_cache_, Vector<const char>::cast(literal_one_byte_string()),
+ unicode_cache_,
+ literal_one_byte_string(),
ALLOW_HEX | ALLOW_OCTAL | ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
}
@@ -1201,7 +1202,7 @@
int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY;
double double_value = StringToDouble(
- unicode_constants_, Vector<const char>::cast(key), flags, 0.0);
+ unicode_constants_, key, flags, 0.0);
int length;
const char* string;
if (!std::isfinite(double_value)) {
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index 1bf6100..e7bf069 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -1277,6 +1277,7 @@
InlineCacheState state) {
Code::Flags flags = Code::ComputeFlags(kind, state, extra_state(), type);
Handle<Code> code = GetCodeWithFlags(flags, name);
+ IC::RegisterWeakMapDependency(code);
PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name));
JitEvent(name, code);
return code;
diff --git a/src/transitions.cc b/src/transitions.cc
index 43a0eb7..33b2475 100644
--- a/src/transitions.cc
+++ b/src/transitions.cc
@@ -35,34 +35,21 @@
namespace internal {
-static MaybeObject* AllocateRaw(Isolate* isolate, int length) {
- // Use FixedArray to not use TransitionArray::cast on incomplete object.
- FixedArray* array;
- MaybeObject* maybe_array = isolate->heap()->AllocateFixedArray(length);
- if (!maybe_array->To(&array)) return maybe_array;
- return array;
-}
-
-
-MaybeObject* TransitionArray::Allocate(Isolate* isolate,
- int number_of_transitions) {
- FixedArray* array;
- MaybeObject* maybe_array =
- AllocateRaw(isolate, ToKeyIndex(number_of_transitions));
- if (!maybe_array->To(&array)) return maybe_array;
+Handle<TransitionArray> TransitionArray::Allocate(Isolate* isolate,
+ int number_of_transitions) {
+ Handle<FixedArray> array =
+ isolate->factory()->NewFixedArray(ToKeyIndex(number_of_transitions));
array->set(kPrototypeTransitionsIndex, Smi::FromInt(0));
- return array;
+ return Handle<TransitionArray>::cast(array);
}
-MaybeObject* TransitionArray::AllocateSimple(Isolate* isolate,
- Map* target) {
- FixedArray* array;
- MaybeObject* maybe_array =
- AllocateRaw(isolate, kSimpleTransitionSize);
- if (!maybe_array->To(&array)) return maybe_array;
- array->set(kSimpleTransitionTarget, target);
- return array;
+Handle<TransitionArray> TransitionArray::AllocateSimple(Isolate* isolate,
+ Handle<Map> target) {
+ Handle<FixedArray> array =
+ isolate->factory()->NewFixedArray(kSimpleTransitionSize);
+ array->set(kSimpleTransitionTarget, *target);
+ return Handle<TransitionArray>::cast(array);
}
@@ -85,12 +72,12 @@
Handle<Map> target,
SimpleTransitionFlag flag) {
Handle<TransitionArray> result;
- Factory* factory = name->GetIsolate()->factory();
+ Isolate* isolate = name->GetIsolate();
if (flag == SIMPLE_TRANSITION) {
- result = factory->NewSimpleTransitionArray(target);
+ result = AllocateSimple(isolate, target);
} else {
- result = factory->NewTransitionArray(1);
+ result = Allocate(isolate, 1);
result->NoIncrementalWriteBarrierSet(0, *name, *target);
}
result->set_back_pointer_storage(map->GetBackPointer());
@@ -98,18 +85,25 @@
}
-MaybeObject* TransitionArray::ExtendToFullTransitionArray() {
- ASSERT(!IsFullTransitionArray());
- int nof = number_of_transitions();
- TransitionArray* result;
- MaybeObject* maybe_result = Allocate(GetIsolate(), nof);
- if (!maybe_result->To(&result)) return maybe_result;
+Handle<TransitionArray> TransitionArray::ExtendToFullTransitionArray(
+ Handle<Map> containing_map) {
+ ASSERT(!containing_map->transitions()->IsFullTransitionArray());
+ int nof = containing_map->transitions()->number_of_transitions();
- if (nof == 1) {
- result->NoIncrementalWriteBarrierCopyFrom(this, kSimpleTransitionIndex, 0);
+ // A transition array may shrink during GC.
+ Handle<TransitionArray> result = Allocate(containing_map->GetIsolate(), nof);
+ DisallowHeapAllocation no_gc;
+ int new_nof = containing_map->transitions()->number_of_transitions();
+ if (new_nof != nof) {
+ ASSERT(new_nof == 0);
+ result->Shrink(ToKeyIndex(0));
+ } else if (nof == 1) {
+ result->NoIncrementalWriteBarrierCopyFrom(
+ containing_map->transitions(), kSimpleTransitionIndex, 0);
}
- result->set_back_pointer_storage(back_pointer_storage());
+ result->set_back_pointer_storage(
+ containing_map->transitions()->back_pointer_storage());
return result;
}
@@ -128,8 +122,7 @@
int insertion_index = map->transitions()->Search(*name);
if (insertion_index == kNotFound) ++new_size;
- Handle<TransitionArray> result =
- map->GetIsolate()->factory()->NewTransitionArray(new_size);
+ Handle<TransitionArray> result = Allocate(map->GetIsolate(), new_size);
// The map's transition array may have disappeared or grown smaller during
// the allocation above as it was weakly traversed. Trim the result copy if
diff --git a/src/transitions.h b/src/transitions.h
index f23523e..e0ec8a0 100644
--- a/src/transitions.h
+++ b/src/transitions.h
@@ -95,13 +95,10 @@
inline int number_of_entries() { return number_of_transitions(); }
- // Allocate a new transition array with a single entry.
- static Handle<TransitionArray> NewWith(Handle<Map> map,
- Handle<Name> name,
- Handle<Map> target,
- SimpleTransitionFlag flag);
-
- MUST_USE_RESULT MaybeObject* ExtendToFullTransitionArray();
+ // Creates a FullTransitionArray from a SimpleTransitionArray in
+ // containing_map.
+ static Handle<TransitionArray> ExtendToFullTransitionArray(
+ Handle<Map> containing_map);
// Create a transition array, copying from the owning map if it already has
// one, otherwise creating a new one according to flag.
@@ -112,21 +109,13 @@
Handle<Map> target,
SimpleTransitionFlag flag);
- // Copy a single transition from the origin array.
- inline void NoIncrementalWriteBarrierCopyFrom(TransitionArray* origin,
- int origin_transition,
- int target_transition);
-
// Search a transition for a given property name.
inline int Search(Name* name);
// Allocates a TransitionArray.
- MUST_USE_RESULT static MaybeObject* Allocate(
+ static Handle<TransitionArray> Allocate(
Isolate* isolate, int number_of_transitions);
- MUST_USE_RESULT static MaybeObject* AllocateSimple(
- Isolate* isolate, Map* target);
-
bool IsSimpleTransition() {
return length() == kSimpleTransitionSize &&
get(kSimpleTransitionTarget)->IsHeapObject() &&
@@ -204,10 +193,24 @@
kTransitionTarget;
}
+ static Handle<TransitionArray> AllocateSimple(
+ Isolate* isolate, Handle<Map> target);
+
+ // Allocate a new transition array with a single entry.
+ static Handle<TransitionArray> NewWith(Handle<Map> map,
+ Handle<Name> name,
+ Handle<Map> target,
+ SimpleTransitionFlag flag);
+
inline void NoIncrementalWriteBarrierSet(int transition_number,
Name* key,
Map* target);
+ // Copy a single transition from the origin array.
+ inline void NoIncrementalWriteBarrierCopyFrom(TransitionArray* origin,
+ int origin_transition,
+ int target_transition);
+
DISALLOW_IMPLICIT_CONSTRUCTORS(TransitionArray);
};
diff --git a/src/types-inl.h b/src/types-inl.h
index 2c80503..ad1107b 100644
--- a/src/types-inl.h
+++ b/src/types-inl.h
@@ -13,6 +13,20 @@
namespace v8 {
namespace internal {
+template<class Config>
+bool TypeImpl<Config>::NowContains(i::Object* value) {
+ DisallowHeapAllocation no_allocation;
+ if (this->IsAny()) return true;
+ if (value->IsHeapObject()) {
+ i::Map* map = i::HeapObject::cast(value)->map();
+ for (Iterator<i::Map> it = this->Classes(); !it.Done(); it.Advance()) {
+ if (*it.Current() == map) return true;
+ }
+ }
+ return this->Contains(value);
+}
+
+
// static
Type* ZoneTypeConfig::handle(Type* type) {
return type;
diff --git a/src/types.cc b/src/types.cc
index 3abc08d..4526b6f 100644
--- a/src/types.cc
+++ b/src/types.cc
@@ -372,19 +372,6 @@
template<class Config>
-bool TypeImpl<Config>::NowContains(i::Object* value) {
- DisallowHeapAllocation no_allocation;
- if (value->IsHeapObject()) {
- i::Map* map = i::HeapObject::cast(value)->map();
- for (Iterator<i::Map> it = this->Classes(); !it.Done(); it.Advance()) {
- if (*it.Current() == map) return true;
- }
- }
- return this->Contains(value);
-}
-
-
-template<class Config>
bool TypeImpl<Config>::InUnion(StructHandle unioned, int current_size) {
ASSERT(!this->IsUnion());
for (int i = 0; i < current_size; ++i) {
diff --git a/src/types.h b/src/types.h
index 18b2223..da63e5f 100644
--- a/src/types.h
+++ b/src/types.h
@@ -271,7 +271,7 @@
bool NowIs(TypeImpl* that);
template<class TypeHandle>
bool NowIs(TypeHandle that) { return this->NowIs(*that); }
- bool NowContains(i::Object* val);
+ inline bool NowContains(i::Object* val);
bool NowContains(i::Handle<i::Object> val) { return this->NowContains(*val); }
bool IsClass() { return Config::is_class(this); }
diff --git a/src/v8conversions.cc b/src/v8conversions.cc
index 900b62d..b891a3e 100644
--- a/src/v8conversions.cc
+++ b/src/v8conversions.cc
@@ -30,6 +30,7 @@
#include "v8.h"
+#include "assert-scope.h"
#include "conversions-inl.h"
#include "v8conversions.h"
#include "dtoa.h"
@@ -81,51 +82,18 @@
double StringToDouble(UnicodeCache* unicode_cache,
- String* str, int flags, double empty_string_val) {
- StringShape shape(str);
- // TODO(dcarney): Use a Visitor here.
- if (shape.IsSequentialAscii()) {
- const uint8_t* begin = SeqOneByteString::cast(str)->GetChars();
- const uint8_t* end = begin + str->length();
- return InternalStringToDouble(unicode_cache, begin, end, flags,
- empty_string_val);
- } else if (shape.IsSequentialTwoByte()) {
- const uc16* begin = SeqTwoByteString::cast(str)->GetChars();
- const uc16* end = begin + str->length();
- return InternalStringToDouble(unicode_cache, begin, end, flags,
- empty_string_val);
+ String* string,
+ int flags,
+ double empty_string_val) {
+ DisallowHeapAllocation no_gc;
+ String::FlatContent flat = string->GetFlatContent();
+ // ECMA-262 section 15.1.2.3, empty string is NaN
+ if (flat.IsAscii()) {
+ return StringToDouble(
+ unicode_cache, flat.ToOneByteVector(), flags, empty_string_val);
} else {
- ConsStringIteratorOp op;
- StringCharacterStream stream(str, &op);
- return InternalStringToDouble(unicode_cache,
- StringCharacterStreamIterator(&stream),
- StringCharacterStreamIterator::EndMarker(),
- flags,
- empty_string_val);
- }
-}
-
-
-double StringToInt(UnicodeCache* unicode_cache,
- String* str,
- int radix) {
- StringShape shape(str);
- // TODO(dcarney): Use a Visitor here.
- if (shape.IsSequentialAscii()) {
- const uint8_t* begin = SeqOneByteString::cast(str)->GetChars();
- const uint8_t* end = begin + str->length();
- return InternalStringToInt(unicode_cache, begin, end, radix);
- } else if (shape.IsSequentialTwoByte()) {
- const uc16* begin = SeqTwoByteString::cast(str)->GetChars();
- const uc16* end = begin + str->length();
- return InternalStringToInt(unicode_cache, begin, end, radix);
- } else {
- ConsStringIteratorOp op;
- StringCharacterStream stream(str, &op);
- return InternalStringToInt(unicode_cache,
- StringCharacterStreamIterator(&stream),
- StringCharacterStreamIterator::EndMarker(),
- radix);
+ return StringToDouble(
+ unicode_cache, flat.ToUC16Vector(), flags, empty_string_val);
}
}
diff --git a/src/v8conversions.h b/src/v8conversions.h
index f2568c0..b38dde7 100644
--- a/src/v8conversions.h
+++ b/src/v8conversions.h
@@ -64,14 +64,11 @@
}
-// Converts a string into a double value according to ECMA-262 9.3.1
double StringToDouble(UnicodeCache* unicode_cache,
- String* str,
+ String* string,
int flags,
- double empty_string_val = 0);
+ double empty_string_val = 0.0);
-// Converts a string into an integer.
-double StringToInt(UnicodeCache* unicode_cache, String* str, int radix);
inline bool TryNumberToSize(Isolate* isolate,
Object* number, size_t* result) {
diff --git a/src/version.cc b/src/version.cc
index b3e0289..ae0587d 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 26
-#define BUILD_NUMBER 12
+#define BUILD_NUMBER 13
#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc
index 75eeff5..19bd828 100644
--- a/src/x64/assembler-x64.cc
+++ b/src/x64/assembler-x64.cc
@@ -1389,6 +1389,15 @@
}
+void Assembler::movsxbl(Register dst, const Operand& src) {
+ EnsureSpace ensure_space(this);
+ emit_optional_rex_32(dst, src);
+ emit(0x0F);
+ emit(0xBE);
+ emit_operand(dst, src);
+}
+
+
void Assembler::movsxbq(Register dst, const Operand& src) {
EnsureSpace ensure_space(this);
emit_rex_64(dst, src);
@@ -1398,6 +1407,15 @@
}
+void Assembler::movsxwl(Register dst, const Operand& src) {
+ EnsureSpace ensure_space(this);
+ emit_optional_rex_32(dst, src);
+ emit(0x0F);
+ emit(0xBF);
+ emit_operand(dst, src);
+}
+
+
void Assembler::movsxwq(Register dst, const Operand& src) {
EnsureSpace ensure_space(this);
emit_rex_64(dst, src);
diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h
index 9009e4f..ebcd532 100644
--- a/src/x64/assembler-x64.h
+++ b/src/x64/assembler-x64.h
@@ -794,7 +794,9 @@
void movq(Register dst, int64_t value);
void movq(Register dst, uint64_t value);
+ void movsxbl(Register dst, const Operand& src);
void movsxbq(Register dst, const Operand& src);
+ void movsxwl(Register dst, const Operand& src);
void movsxwq(Register dst, const Operand& src);
void movsxlq(Register dst, Register src);
void movsxlq(Register dst, const Operand& src);
diff --git a/src/x64/debug-x64.cc b/src/x64/debug-x64.cc
index 36d5df6..a65dd29 100644
--- a/src/x64/debug-x64.cc
+++ b/src/x64/debug-x64.cc
@@ -124,7 +124,7 @@
__ Push(reg);
}
if ((non_object_regs & (1 << r)) != 0) {
- __ PushInt64AsTwoSmis(reg);
+ __ PushRegisterAsTwoSmis(reg);
}
}
@@ -149,7 +149,7 @@
}
// Reconstruct the 64-bit value from two smis.
if ((non_object_regs & (1 << r)) != 0) {
- __ PopInt64AsTwoSmis(reg);
+ __ PopRegisterAsTwoSmis(reg);
}
}
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index 8962267..1d5480f 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -4530,12 +4530,13 @@
}
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
- if (check->Equals(isolate()->heap()->number_string())) {
+ Factory* factory = isolate()->factory();
+ if (String::Equals(check, factory->number_string())) {
__ JumpIfSmi(rax, if_true);
__ movp(rax, FieldOperand(rax, HeapObject::kMapOffset));
__ CompareRoot(rax, Heap::kHeapNumberMapRootIndex);
Split(equal, if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->string_string())) {
+ } else if (String::Equals(check, factory->string_string())) {
__ JumpIfSmi(rax, if_false);
// Check for undetectable objects => false.
__ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx);
@@ -4543,20 +4544,20 @@
__ testb(FieldOperand(rdx, Map::kBitFieldOffset),
Immediate(1 << Map::kIsUndetectable));
Split(zero, if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->symbol_string())) {
+ } else if (String::Equals(check, factory->symbol_string())) {
__ JumpIfSmi(rax, if_false);
__ CmpObjectType(rax, SYMBOL_TYPE, rdx);
Split(equal, if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->boolean_string())) {
+ } else if (String::Equals(check, factory->boolean_string())) {
__ CompareRoot(rax, Heap::kTrueValueRootIndex);
__ j(equal, if_true);
__ CompareRoot(rax, Heap::kFalseValueRootIndex);
Split(equal, if_true, if_false, fall_through);
} else if (FLAG_harmony_typeof &&
- check->Equals(isolate()->heap()->null_string())) {
+ String::Equals(check, factory->null_string())) {
__ CompareRoot(rax, Heap::kNullValueRootIndex);
Split(equal, if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->undefined_string())) {
+ } else if (String::Equals(check, factory->undefined_string())) {
__ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
__ j(equal, if_true);
__ JumpIfSmi(rax, if_false);
@@ -4565,14 +4566,14 @@
__ testb(FieldOperand(rdx, Map::kBitFieldOffset),
Immediate(1 << Map::kIsUndetectable));
Split(not_zero, if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->function_string())) {
+ } else if (String::Equals(check, factory->function_string())) {
__ JumpIfSmi(rax, if_false);
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
__ CmpObjectType(rax, JS_FUNCTION_TYPE, rdx);
__ j(equal, if_true);
__ CmpInstanceType(rdx, JS_FUNCTION_PROXY_TYPE);
Split(equal, if_true, if_false, fall_through);
- } else if (check->Equals(isolate()->heap()->object_string())) {
+ } else if (String::Equals(check, factory->object_string())) {
__ JumpIfSmi(rax, if_false);
if (!FLAG_harmony_typeof) {
__ CompareRoot(rax, Heap::kNullValueRootIndex);
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index 706b9f1..89f7cd0 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -284,6 +284,12 @@
void LCodeGen::GenerateBodyInstructionPost(LInstruction* instr) {
+ if (FLAG_debug_code && FLAG_enable_slow_asserts && instr->HasResult() &&
+ instr->hydrogen_value()->representation().IsInteger32() &&
+ instr->result()->IsRegister()) {
+ __ AssertZeroExtended(ToRegister(instr->result()));
+ }
+
if (instr->HasResult() && instr->MustSignExtendResult(chunk())) {
if (instr->result()->IsRegister()) {
Register result_reg = ToRegister(instr->result());
@@ -1321,7 +1327,7 @@
}
__ TruncatingDiv(dividend, Abs(divisor));
- if (divisor < 0) __ negp(rdx);
+ if (divisor < 0) __ negl(rdx);
if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
__ movl(rax, rdx);
@@ -1525,13 +1531,25 @@
} else if (right->IsStackSlot()) {
switch (instr->op()) {
case Token::BIT_AND:
- __ andp(ToRegister(left), ToOperand(right));
+ if (instr->IsInteger32()) {
+ __ andl(ToRegister(left), ToOperand(right));
+ } else {
+ __ andp(ToRegister(left), ToOperand(right));
+ }
break;
case Token::BIT_OR:
- __ orp(ToRegister(left), ToOperand(right));
+ if (instr->IsInteger32()) {
+ __ orl(ToRegister(left), ToOperand(right));
+ } else {
+ __ orp(ToRegister(left), ToOperand(right));
+ }
break;
case Token::BIT_XOR:
- __ xorp(ToRegister(left), ToOperand(right));
+ if (instr->IsInteger32()) {
+ __ xorl(ToRegister(left), ToOperand(right));
+ } else {
+ __ xorp(ToRegister(left), ToOperand(right));
+ }
break;
default:
UNREACHABLE();
@@ -1541,13 +1559,25 @@
ASSERT(right->IsRegister());
switch (instr->op()) {
case Token::BIT_AND:
- __ andp(ToRegister(left), ToRegister(right));
+ if (instr->IsInteger32()) {
+ __ andl(ToRegister(left), ToRegister(right));
+ } else {
+ __ andp(ToRegister(left), ToRegister(right));
+ }
break;
case Token::BIT_OR:
- __ orp(ToRegister(left), ToRegister(right));
+ if (instr->IsInteger32()) {
+ __ orl(ToRegister(left), ToRegister(right));
+ } else {
+ __ orp(ToRegister(left), ToRegister(right));
+ }
break;
case Token::BIT_XOR:
- __ xorp(ToRegister(left), ToRegister(right));
+ if (instr->IsInteger32()) {
+ __ xorl(ToRegister(left), ToRegister(right));
+ } else {
+ __ xorp(ToRegister(left), ToRegister(right));
+ }
break;
default:
UNREACHABLE();
@@ -1654,7 +1684,12 @@
void LCodeGen::DoConstantI(LConstantI* instr) {
- __ Set(ToRegister(instr->result()), instr->value());
+ Register dst = ToRegister(instr->result());
+ if (instr->value() == 0) {
+ __ xorl(dst, dst);
+ } else {
+ __ movl(dst, Immediate(instr->value()));
+ }
}
@@ -2904,11 +2939,11 @@
Representation representation = access.representation();
if (representation.IsSmi() && SmiValuesAre32Bits() &&
instr->hydrogen()->representation().IsInteger32()) {
-#ifdef DEBUG
- Register scratch = kScratchRegister;
- __ Load(scratch, FieldOperand(object, offset), representation);
- __ AssertSmi(scratch);
-#endif
+ if (FLAG_debug_code) {
+ Register scratch = kScratchRegister;
+ __ Load(scratch, FieldOperand(object, offset), representation);
+ __ AssertSmi(scratch);
+ }
// Read int value directly from upper half of the smi.
STATIC_ASSERT(kSmiTag == 0);
@@ -3035,25 +3070,25 @@
switch (elements_kind) {
case EXTERNAL_INT8_ELEMENTS:
case INT8_ELEMENTS:
- __ movsxbq(result, operand);
+ __ movsxbl(result, operand);
break;
case EXTERNAL_UINT8_ELEMENTS:
case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
case UINT8_ELEMENTS:
case UINT8_CLAMPED_ELEMENTS:
- __ movzxbp(result, operand);
+ __ movzxbl(result, operand);
break;
case EXTERNAL_INT16_ELEMENTS:
case INT16_ELEMENTS:
- __ movsxwq(result, operand);
+ __ movsxwl(result, operand);
break;
case EXTERNAL_UINT16_ELEMENTS:
case UINT16_ELEMENTS:
- __ movzxwp(result, operand);
+ __ movzxwl(result, operand);
break;
case EXTERNAL_INT32_ELEMENTS:
case INT32_ELEMENTS:
- __ movsxlq(result, operand);
+ __ movl(result, operand);
break;
case EXTERNAL_UINT32_ELEMENTS:
case UINT32_ELEMENTS:
@@ -3119,17 +3154,17 @@
if (representation.IsInteger32() && SmiValuesAre32Bits() &&
hinstr->elements_kind() == FAST_SMI_ELEMENTS) {
ASSERT(!requires_hole_check);
-#ifdef DEBUG
- Register scratch = kScratchRegister;
- __ Load(scratch,
- BuildFastArrayOperand(instr->elements(),
- key,
- FAST_ELEMENTS,
- offset,
- instr->additional_index()),
- Representation::Smi());
- __ AssertSmi(scratch);
-#endif
+ if (FLAG_debug_code) {
+ Register scratch = kScratchRegister;
+ __ Load(scratch,
+ BuildFastArrayOperand(instr->elements(),
+ key,
+ FAST_ELEMENTS,
+ offset,
+ instr->additional_index()),
+ Representation::Smi());
+ __ AssertSmi(scratch);
+ }
// Read int value directly from upper half of the smi.
STATIC_ASSERT(kSmiTag == 0);
ASSERT(kSmiTagSize + kSmiShiftSize == 32);
@@ -4043,11 +4078,11 @@
if (representation.IsSmi() && SmiValuesAre32Bits() &&
hinstr->value()->representation().IsInteger32()) {
ASSERT(hinstr->store_mode() == STORE_TO_INITIALIZED_ENTRY);
-#ifdef DEBUG
- Register scratch = kScratchRegister;
- __ Load(scratch, FieldOperand(write_register, offset), representation);
- __ AssertSmi(scratch);
-#endif
+ if (FLAG_debug_code) {
+ Register scratch = kScratchRegister;
+ __ Load(scratch, FieldOperand(write_register, offset), representation);
+ __ AssertSmi(scratch);
+ }
// Store int value directly to upper half of the smi.
STATIC_ASSERT(kSmiTag == 0);
ASSERT(kSmiTagSize + kSmiShiftSize == 32);
@@ -4266,17 +4301,17 @@
if (representation.IsInteger32() && SmiValuesAre32Bits()) {
ASSERT(hinstr->store_mode() == STORE_TO_INITIALIZED_ENTRY);
ASSERT(hinstr->elements_kind() == FAST_SMI_ELEMENTS);
-#ifdef DEBUG
- Register scratch = kScratchRegister;
- __ Load(scratch,
- BuildFastArrayOperand(instr->elements(),
- key,
- FAST_ELEMENTS,
- offset,
- instr->additional_index()),
- Representation::Smi());
- __ AssertSmi(scratch);
-#endif
+ if (FLAG_debug_code) {
+ Register scratch = kScratchRegister;
+ __ Load(scratch,
+ BuildFastArrayOperand(instr->elements(),
+ key,
+ FAST_ELEMENTS,
+ offset,
+ instr->additional_index()),
+ Representation::Smi());
+ __ AssertSmi(scratch);
+ }
// Store int value directly to upper half of the smi.
STATIC_ASSERT(kSmiTag == 0);
ASSERT(kSmiTagSize + kSmiShiftSize == 32);
@@ -5336,14 +5371,15 @@
Label::Distance false_distance = right_block == next_block ? Label::kNear
: Label::kFar;
Condition final_branch_condition = no_condition;
- if (type_name->Equals(heap()->number_string())) {
+ Factory* factory = isolate()->factory();
+ if (String::Equals(type_name, factory->number_string())) {
__ JumpIfSmi(input, true_label, true_distance);
__ CompareRoot(FieldOperand(input, HeapObject::kMapOffset),
Heap::kHeapNumberMapRootIndex);
final_branch_condition = equal;
- } else if (type_name->Equals(heap()->string_string())) {
+ } else if (String::Equals(type_name, factory->string_string())) {
__ JumpIfSmi(input, false_label, false_distance);
__ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);
__ j(above_equal, false_label, false_distance);
@@ -5351,22 +5387,23 @@
Immediate(1 << Map::kIsUndetectable));
final_branch_condition = zero;
- } else if (type_name->Equals(heap()->symbol_string())) {
+ } else if (String::Equals(type_name, factory->symbol_string())) {
__ JumpIfSmi(input, false_label, false_distance);
__ CmpObjectType(input, SYMBOL_TYPE, input);
final_branch_condition = equal;
- } else if (type_name->Equals(heap()->boolean_string())) {
+ } else if (String::Equals(type_name, factory->boolean_string())) {
__ CompareRoot(input, Heap::kTrueValueRootIndex);
__ j(equal, true_label, true_distance);
__ CompareRoot(input, Heap::kFalseValueRootIndex);
final_branch_condition = equal;
- } else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_string())) {
+ } else if (FLAG_harmony_typeof &&
+ String::Equals(type_name, factory->null_string())) {
__ CompareRoot(input, Heap::kNullValueRootIndex);
final_branch_condition = equal;
- } else if (type_name->Equals(heap()->undefined_string())) {
+ } else if (String::Equals(type_name, factory->undefined_string())) {
__ CompareRoot(input, Heap::kUndefinedValueRootIndex);
__ j(equal, true_label, true_distance);
__ JumpIfSmi(input, false_label, false_distance);
@@ -5376,7 +5413,7 @@
Immediate(1 << Map::kIsUndetectable));
final_branch_condition = not_zero;
- } else if (type_name->Equals(heap()->function_string())) {
+ } else if (String::Equals(type_name, factory->function_string())) {
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
__ JumpIfSmi(input, false_label, false_distance);
__ CmpObjectType(input, JS_FUNCTION_TYPE, input);
@@ -5384,7 +5421,7 @@
__ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE);
final_branch_condition = equal;
- } else if (type_name->Equals(heap()->object_string())) {
+ } else if (String::Equals(type_name, factory->object_string())) {
__ JumpIfSmi(input, false_label, false_distance);
if (!FLAG_harmony_typeof) {
__ CompareRoot(input, Heap::kNullValueRootIndex);
diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h
index 1c8bb0d..43a676c 100644
--- a/src/x64/lithium-x64.h
+++ b/src/x64/lithium-x64.h
@@ -1246,6 +1246,9 @@
LOperand* right() { return inputs_[1]; }
Token::Value op() const { return hydrogen()->op(); }
+ bool IsInteger32() const {
+ return hydrogen()->representation().IsInteger32();
+ }
DECLARE_CONCRETE_INSTRUCTION(BitI, "bit-i")
DECLARE_HYDROGEN_ACCESSOR(Bitwise)
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index 693a5c6..b36f4f0 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -2283,10 +2283,11 @@
}
-void MacroAssembler::PushInt64AsTwoSmis(Register src, Register scratch) {
+void MacroAssembler::PushRegisterAsTwoSmis(Register src, Register scratch) {
+ ASSERT(!src.is(scratch));
movp(scratch, src);
// High bits.
- shrp(src, Immediate(64 - kSmiShift));
+ shrp(src, Immediate(kPointerSize * kBitsPerByte - kSmiShift));
shlp(src, Immediate(kSmiShift));
Push(src);
// Low bits.
@@ -2295,14 +2296,15 @@
}
-void MacroAssembler::PopInt64AsTwoSmis(Register dst, Register scratch) {
+void MacroAssembler::PopRegisterAsTwoSmis(Register dst, Register scratch) {
+ ASSERT(!dst.is(scratch));
Pop(scratch);
// Low bits.
shrp(scratch, Immediate(kSmiShift));
Pop(dst);
shrp(dst, Immediate(kSmiShift));
// High bits.
- shlp(dst, Immediate(64 - kSmiShift));
+ shlp(dst, Immediate(kPointerSize * kBitsPerByte - kSmiShift));
orp(dst, scratch);
}
@@ -3276,6 +3278,8 @@
}
bind(&done);
+ // Keep our invariant that the upper 32 bits are zero.
+ movl(result_reg, result_reg);
}
@@ -3292,6 +3296,8 @@
addp(rsp, Immediate(kDoubleSize));
bind(&done);
+ // Keep our invariant that the upper 32 bits are zero.
+ movl(result_reg, result_reg);
}
diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h
index ee4fb85..4a2fa8e 100644
--- a/src/x64/macro-assembler-x64.h
+++ b/src/x64/macro-assembler-x64.h
@@ -726,12 +726,12 @@
void Push(Smi* smi);
- // Save away a 64-bit integer on the stack as two 32-bit integers
+ // Save away a raw integer with pointer size on the stack as two integers
// masquerading as smis so that the garbage collector skips visiting them.
- void PushInt64AsTwoSmis(Register src, Register scratch = kScratchRegister);
- // Reconstruct a 64-bit integer from two 32-bit integers masquerading as
- // smis on the top of stack.
- void PopInt64AsTwoSmis(Register dst, Register scratch = kScratchRegister);
+ void PushRegisterAsTwoSmis(Register src, Register scratch = kScratchRegister);
+ // Reconstruct a raw integer with pointer size from two integers masquerading
+ // as smis on the top of stack.
+ void PopRegisterAsTwoSmis(Register dst, Register scratch = kScratchRegister);
void Test(const Operand& dst, Smi* source);