Index: runtime/vm/dart_api_impl.cc |
=================================================================== |
--- runtime/vm/dart_api_impl.cc (revision 3821) |
+++ runtime/vm/dart_api_impl.cc (working copy) |
@@ -14,6 +14,7 @@ |
#include "vm/debuginfo.h" |
#include "vm/exceptions.h" |
#include "vm/growable_array.h" |
+#include "vm/longjump.h" |
#include "vm/message.h" |
#include "vm/native_entry.h" |
#include "vm/native_message_handler.h" |
@@ -86,6 +87,53 @@ |
} |
+// NOTE: Need to pass 'result' as a parameter here in order to avoid |
+// warning: variable 'result' might be clobbered by 'longjmp' or 'vfork' |
+// which shows up because of the use of setjmp. |
+static void InvokeStatic(Isolate* isolate, |
+ const Function& function, |
+ GrowableArray<const Object*>& args, |
+ Dart_Handle* result) { |
+ ASSERT(isolate != NULL); |
+ LongJump* base = isolate->long_jump_base(); |
+ LongJump jump; |
+ isolate->set_long_jump_base(&jump); |
+ if (setjmp(*jump.Set()) == 0) { |
+ const Array& kNoArgumentNames = Array::Handle(); |
+ const Instance& retval = Instance::Handle( |
+ DartEntry::InvokeStatic(function, args, kNoArgumentNames)); |
+ *result = Api::NewLocalHandle(retval); |
+ } else { |
+ SetupErrorResult(result); |
+ } |
+ isolate->set_long_jump_base(base); |
+} |
+ |
+ |
+// NOTE: Need to pass 'result' as a parameter here in order to avoid |
+// warning: variable 'result' might be clobbered by 'longjmp' or 'vfork' |
+// which shows up because of the use of setjmp. |
+static void InvokeDynamic(Isolate* isolate, |
+ const Instance& receiver, |
+ const Function& function, |
+ GrowableArray<const Object*>& args, |
+ Dart_Handle* result) { |
+ ASSERT(isolate != NULL); |
+ LongJump* base = isolate->long_jump_base(); |
+ LongJump jump; |
+ isolate->set_long_jump_base(&jump); |
+ if (setjmp(*jump.Set()) == 0) { |
+ const Array& kNoArgumentNames = Array::Handle(); |
+ const Instance& retval = Instance::Handle( |
+ DartEntry::InvokeDynamic(receiver, function, args, kNoArgumentNames)); |
+ *result = Api::NewLocalHandle(retval); |
+ } else { |
+ SetupErrorResult(result); |
+ } |
+ isolate->set_long_jump_base(base); |
+} |
+ |
+ |
Dart_Handle Api::NewLocalHandle(const Object& object) { |
Isolate* isolate = Isolate::Current(); |
ASSERT(isolate != NULL); |
@@ -325,33 +373,6 @@ |
} |
-DART_EXPORT Dart_Handle Dart_PropagateError(Dart_Handle handle) { |
- Isolate* isolate = Isolate::Current(); |
- CHECK_ISOLATE(isolate); |
- const Object& error = Object::Handle(Api::UnwrapHandle(handle)); |
- if (!error.IsError()) { |
- return Api::NewError( |
- "%s expects argument 'handle' to be an error handle. " |
- "Did you forget to check Dart_IsError first?", |
- CURRENT_FUNC); |
- } |
- if (isolate->top_exit_frame_info() == 0) { |
- // There are no dart frames on the stack so it would be illegal to |
- // propagate an error here. |
- return Api::NewError("No Dart frames on stack, cannot propagate error."); |
- } |
- |
- // Unwind all the API scopes till the exit frame before propagating. |
- ApiState* state = isolate->api_state(); |
- ASSERT(state != NULL); |
- state->UnwindScopes(isolate->top_exit_frame_info()); |
- Exceptions::PropagateError(error); |
- UNREACHABLE(); |
- |
- return Api::NewError("Cannot reach here. Internal error."); |
-} |
- |
- |
DART_EXPORT void _Dart_ReportErrorHandle(const char* file, |
int line, |
const char* handle, |
@@ -479,17 +500,24 @@ |
char** error) { |
Isolate* isolate = Dart::CreateIsolate(name_prefix); |
assert(isolate != NULL); |
- DARTSCOPE_NOCHECKS(isolate); |
- const Error& error_obj = |
- Error::Handle(Dart::InitializeIsolate(snapshot, callback_data)); |
- if (error_obj.IsNull()) { |
+ LongJump* base = isolate->long_jump_base(); |
+ LongJump jump; |
+ isolate->set_long_jump_base(&jump); |
+ if (setjmp(*jump.Set()) == 0) { |
+ Dart::InitializeIsolate(snapshot, callback_data); |
START_TIMER(time_total_runtime); |
+ isolate->set_long_jump_base(base); |
return reinterpret_cast<Dart_Isolate>(isolate); |
} else { |
- *error = strdup(error_obj.ToErrorCString()); |
+ { |
+ DARTSCOPE_NOCHECKS(isolate); |
+ const Error& error_obj = |
+ Error::Handle(isolate->object_store()->sticky_error()); |
+ *error = strdup(error_obj.ToErrorCString()); |
+ } |
Dart::ShutdownIsolate(); |
- return reinterpret_cast<Dart_Isolate>(NULL); |
} |
+ return reinterpret_cast<Dart_Isolate>(NULL); |
} |
@@ -608,12 +636,24 @@ |
DART_EXPORT Dart_Handle Dart_RunLoop() { |
Isolate* isolate = Isolate::Current(); |
DARTSCOPE(isolate); |
- const Object& obj = Object::Handle(isolate->StandardRunLoop()); |
- if (obj.IsError()) { |
- return Api::NewLocalHandle(obj); |
+ |
+ LongJump* base = isolate->long_jump_base(); |
+ LongJump jump; |
+ Dart_Handle result; |
+ isolate->set_long_jump_base(&jump); |
+ if (setjmp(*jump.Set()) == 0) { |
+ const Object& obj = Object::Handle(isolate->StandardRunLoop()); |
+ if (obj.IsError()) { |
+ result = Api::NewLocalHandle(obj); |
+ } else { |
+ ASSERT(obj.IsNull()); |
+ result = Api::Success(); |
+ } |
+ } else { |
+ SetupErrorResult(&result); |
} |
- ASSERT(obj.IsNull()); |
- return Api::Success(); |
+ isolate->set_long_jump_base(base); |
+ return result; |
} |
@@ -753,9 +793,9 @@ |
Resolver::kIsQualified)); |
GrowableArray<const Object*> arguments(kNumArguments); |
arguments.Add(&Integer::Handle(Integer::New(port_id))); |
- const Object& result = Object::Handle( |
- DartEntry::InvokeStatic(function, arguments, kNoArgumentNames)); |
- return Api::NewLocalHandle(result); |
+ Dart_Handle result; |
+ InvokeStatic(isolate, function, arguments, &result); |
+ return result; |
} |
@@ -777,9 +817,9 @@ |
Resolver::kIsQualified)); |
GrowableArray<const Object*> arguments(kNumArguments); |
arguments.Add(&Integer::Handle(Integer::New(port_id))); |
- const Object& result = Object::Handle( |
- DartEntry::InvokeStatic(function, arguments, kNoArgumentNames)); |
- return Api::NewLocalHandle(result); |
+ Dart_Handle result; |
+ InvokeStatic(isolate, function, arguments, &result); |
+ return result; |
} |
@@ -836,8 +876,8 @@ |
DARTSCOPE(Isolate::Current()); |
const Instance& expected = Instance::CheckedHandle(Api::UnwrapHandle(obj1)); |
const Instance& actual = Instance::CheckedHandle(Api::UnwrapHandle(obj2)); |
- const Object& result = |
- Object::Handle(DartLibraryCalls::Equals(expected, actual)); |
+ const Instance& result = |
+ Instance::Handle(DartLibraryCalls::Equals(expected, actual)); |
if (result.IsBool()) { |
Bool& b = Bool::Handle(); |
b ^= result.raw(); |
@@ -1366,41 +1406,84 @@ |
// TODO(5526318): Make access to GrowableObjectArray more efficient. |
// Now check and handle a dart object that implements the List interface. |
const Instance& instance = Instance::Handle(GetListInstance(isolate, obj)); |
- if (instance.IsNull()) { |
- return Api::NewError("Object does not implement the List inteface"); |
+ if (!instance.IsNull()) { |
+ String& name = String::Handle(String::New("length")); |
+ name = Field::GetterName(name); |
+ const Function& function = Function::Handle( |
+ Resolver::ResolveDynamic(instance, name, 1, 0)); |
+ if (!function.IsNull()) { |
+ GrowableArray<const Object*> args(0); |
+ LongJump* base = isolate->long_jump_base(); |
+ LongJump jump; |
+ isolate->set_long_jump_base(&jump); |
+ Dart_Handle result; |
+ if (setjmp(*jump.Set()) == 0) { |
+ const Array& kNoArgumentNames = Array::Handle(); |
+ const Instance& retval = Instance::Handle( |
+ DartEntry::InvokeDynamic(instance, |
+ function, |
+ args, |
+ kNoArgumentNames)); |
+ result = Api::Success(); |
+ if (retval.IsSmi() || retval.IsMint()) { |
+ Integer& integer = Integer::Handle(); |
+ integer ^= retval.raw(); |
+ *len = integer.AsInt64Value(); |
+ } else if (retval.IsBigint()) { |
+ Bigint& bigint = Bigint::Handle(); |
+ bigint ^= retval.raw(); |
+ if (BigintOperations::FitsIntoInt64(bigint)) { |
+ *len = BigintOperations::ToInt64(bigint); |
+ } else { |
+ result = |
+ Api::NewError("Length of List object is greater than the " |
+ "maximum value that 'len' parameter can hold"); |
+ } |
+ } else if (retval.IsError()) { |
+ result = Api::NewLocalHandle(retval); |
+ } else { |
+ result = Api::NewError("Length of List object is not an integer"); |
+ } |
+ } else { |
+ SetupErrorResult(&result); |
+ } |
+ isolate->set_long_jump_base(base); |
+ return result; |
+ } |
} |
- String& name = String::Handle(String::New("length")); |
- name = Field::GetterName(name); |
- const Function& function = Function::Handle( |
- Resolver::ResolveDynamic(instance, name, 1, 0)); |
- if (function.IsNull()) { |
- return Api::NewError("List object does not have a 'length' field."); |
- } |
+ return Api::NewError("Object does not implement the 'List' inteface"); |
+} |
- GrowableArray<const Object*> args(0); |
- const Array& kNoArgumentNames = Array::Handle(); |
- const Object& retval = Object::Handle( |
- DartEntry::InvokeDynamic(instance, function, args, kNoArgumentNames)); |
- if (retval.IsSmi() || retval.IsMint()) { |
- Integer& integer = Integer::Handle(); |
- integer ^= retval.raw(); |
- *len = integer.AsInt64Value(); |
- return Api::Success(); |
- } else if (retval.IsBigint()) { |
- Bigint& bigint = Bigint::Handle(); |
- bigint ^= retval.raw(); |
- if (BigintOperations::FitsIntoInt64(bigint)) { |
- *len = BigintOperations::ToInt64(bigint); |
- return Api::Success(); |
+static RawObject* GetListAt(Isolate* isolate, |
+ const Instance& instance, |
+ const Integer& index, |
+ const Function& function, |
+ Dart_Handle* result) { |
+ ASSERT(isolate != NULL); |
+ ASSERT(result != NULL); |
+ LongJump* base = isolate->long_jump_base(); |
+ LongJump jump; |
+ isolate->set_long_jump_base(&jump); |
+ if (setjmp(*jump.Set()) == 0) { |
+ Instance& retval = Instance::Handle(); |
+ GrowableArray<const Object*> args(0); |
+ args.Add(&index); |
+ const Array& kNoArgumentNames = Array::Handle(); |
+ retval = DartEntry::InvokeDynamic(instance, |
+ function, |
+ args, |
+ kNoArgumentNames); |
+ if (retval.IsError()) { |
+ *result = Api::NewLocalHandle(retval); |
} else { |
- return Api::NewError("Length of List object is greater than the " |
- "maximum value that 'len' parameter can hold"); |
+ *result = Api::Success(); |
} |
- } else if (retval.IsError()) { |
- return Api::NewLocalHandle(retval); |
- } else { |
- return Api::NewError("Length of List object is not an integer"); |
+ isolate->set_long_jump_base(base); |
+ return retval.raw(); |
} |
+ SetupErrorResult(result); |
+ isolate->set_long_jump_base(base); |
+ return Object::null(); |
} |
@@ -1425,20 +1508,54 @@ |
const Function& function = Function::Handle( |
Resolver::ResolveDynamic(instance, name, 2, 0)); |
if (!function.IsNull()) { |
- GrowableArray<const Object*> args(1); |
+ Object& element = Object::Handle(); |
Integer& indexobj = Integer::Handle(); |
+ Dart_Handle result; |
indexobj = Integer::New(index); |
- args.Add(&indexobj); |
- const Array& kNoArgumentNames = Array::Handle(); |
- const Object& result = Object::Handle( |
- DartEntry::InvokeDynamic(instance, function, args, kNoArgumentNames)); |
- return Api::NewLocalHandle(result); |
+ element = GetListAt(isolate, instance, indexobj, function, &result); |
+ if (::Dart_IsError(result)) { |
+ return result; // Error condition. |
+ } |
+ return Api::NewLocalHandle(element); |
} |
} |
return Api::NewError("Object does not implement the 'List' interface"); |
} |
+static void SetListAt(Isolate* isolate, |
+ const Instance& instance, |
+ const Integer& index, |
+ const Object& value, |
+ const Function& function, |
+ Dart_Handle* result) { |
+ ASSERT(isolate != NULL); |
+ ASSERT(result != NULL); |
+ LongJump* base = isolate->long_jump_base(); |
+ LongJump jump; |
+ isolate->set_long_jump_base(&jump); |
+ if (setjmp(*jump.Set()) == 0) { |
+ GrowableArray<const Object*> args(1); |
+ args.Add(&index); |
+ args.Add(&value); |
+ Instance& retval = Instance::Handle(); |
+ const Array& kNoArgumentNames = Array::Handle(); |
+ retval = DartEntry::InvokeDynamic(instance, |
+ function, |
+ args, |
+ kNoArgumentNames); |
+ if (retval.IsError()) { |
+ *result = Api::NewLocalHandle(retval); |
+ } else { |
+ *result = Api::Success(); |
+ } |
+ } else { |
+ SetupErrorResult(result); |
+ } |
+ isolate->set_long_jump_base(base); |
+} |
+ |
+ |
DART_EXPORT Dart_Handle Dart_ListSetAt(Dart_Handle list, |
intptr_t index, |
Dart_Handle value) { |
@@ -1466,15 +1583,11 @@ |
const Function& function = Function::Handle( |
Resolver::ResolveDynamic(instance, name, 3, 0)); |
if (!function.IsNull()) { |
+ Dart_Handle result; |
const Integer& index_obj = Integer::Handle(Integer::New(index)); |
const Object& value_obj = Object::Handle(Api::UnwrapHandle(value)); |
- GrowableArray<const Object*> args(2); |
- args.Add(&index_obj); |
- args.Add(&value_obj); |
- const Array& kNoArgumentNames = Array::Handle(); |
- const Object& result = Object::Handle( |
- DartEntry::InvokeDynamic(instance, function, args, kNoArgumentNames)); |
- return Api::NewLocalHandle(result); |
+ SetListAt(isolate, instance, index_obj, value_obj, function, &result); |
+ return result; |
} |
} |
return Api::NewError("Object does not implement the 'List' interface"); |
@@ -1527,23 +1640,20 @@ |
const Function& function = Function::Handle( |
Resolver::ResolveDynamic(instance, name, 2, 0)); |
if (!function.IsNull()) { |
- Object& result = Object::Handle(); |
+ Object& element = Object::Handle(); |
Integer& intobj = Integer::Handle(); |
+ Dart_Handle result; |
for (int i = 0; i < length; i++) { |
intobj = Integer::New(offset + i); |
- GrowableArray<const Object*> args(1); |
- args.Add(&intobj); |
- const Array& kNoArgumentNames = Array::Handle(); |
- result = DartEntry::InvokeDynamic( |
- instance, function, args, kNoArgumentNames); |
- if (result.IsError()) { |
- return Api::NewLocalHandle(result); |
+ element = GetListAt(isolate, instance, intobj, function, &result); |
+ if (::Dart_IsError(result)) { |
+ return result; // Error condition. |
} |
- if (!result.IsInteger()) { |
+ if (!element.IsInteger()) { |
return Api::NewError("%s expects the argument 'list' to be " |
- "a List of int", CURRENT_FUNC); |
+ "a List of int", CURRENT_FUNC); |
} |
- intobj ^= result.raw(); |
+ intobj ^= element.raw(); |
ASSERT(intobj.AsInt64Value() <= 0xff); |
// TODO(hpayer): value should always be smaller then 0xff. Add error |
// handling. |
@@ -1591,6 +1701,7 @@ |
// TODO(5526318): Make access to GrowableObjectArray more efficient. |
// Now check and handle a dart object that implements the List interface. |
const Instance& instance = Instance::Handle(GetListInstance(isolate, obj)); |
+ Dart_Handle result; |
if (!instance.IsNull()) { |
String& name = String::Handle(String::New("[]=")); |
const Function& function = Function::Handle( |
@@ -1601,15 +1712,9 @@ |
for (int i = 0; i < length; i++) { |
indexobj = Integer::New(offset + i); |
valueobj = Integer::New(native_array[i]); |
- GrowableArray<const Object*> args(2); |
- args.Add(&indexobj); |
- args.Add(&valueobj); |
- const Array& kNoArgumentNames = Array::Handle(); |
- const Object& result = Object::Handle( |
- DartEntry::InvokeDynamic( |
- instance, function, args, kNoArgumentNames)); |
- if (result.IsError()) { |
- return Api::NewLocalHandle(result); |
+ SetListAt(isolate, instance, indexobj, valueobj, function, &result); |
+ if (::Dart_IsError(result)) { |
+ return result; // Error condition. |
} |
} |
return Api::Success(); |
@@ -1647,6 +1752,29 @@ |
} |
+// NOTE: Need to pass 'result' as a parameter here in order to avoid |
+// warning: variable 'result' might be clobbered by 'longjmp' or 'vfork' |
+// which shows up because of the use of setjmp. |
+static void InvokeClosure(Isolate* isolate, |
+ const Closure& closure, |
+ GrowableArray<const Object*>& args, |
+ Dart_Handle* result) { |
+ ASSERT(isolate != NULL); |
+ LongJump* base = isolate->long_jump_base(); |
+ LongJump jump; |
+ isolate->set_long_jump_base(&jump); |
+ if (setjmp(*jump.Set()) == 0) { |
+ const Array& kNoArgumentNames = Array::Handle(); |
+ const Instance& retval = Instance::Handle( |
+ DartEntry::InvokeClosure(closure, args, kNoArgumentNames)); |
+ *result = Api::NewLocalHandle(retval); |
+ } else { |
+ SetupErrorResult(result); |
+ } |
+ isolate->set_long_jump_base(base); |
+} |
+ |
+ |
DART_EXPORT Dart_Handle Dart_InvokeClosure(Dart_Handle closure, |
int number_of_arguments, |
Dart_Handle* arguments) { |
@@ -1664,15 +1792,14 @@ |
// Now try to invoke the closure. |
Closure& closure_obj = Closure::Handle(); |
closure_obj ^= obj.raw(); |
+ Dart_Handle retval; |
GrowableArray<const Object*> dart_arguments(number_of_arguments); |
for (int i = 0; i < number_of_arguments; i++) { |
const Object& arg = Object::Handle(Api::UnwrapHandle(arguments[i])); |
dart_arguments.Add(&arg); |
} |
- const Array& kNoArgumentNames = Array::Handle(); |
- const Object& result = Object::Handle( |
- DartEntry::InvokeClosure(closure_obj, dart_arguments, kNoArgumentNames)); |
- return Api::NewLocalHandle(result); |
+ InvokeClosure(isolate, closure_obj, dart_arguments, &retval); |
+ return retval; |
} |
@@ -1749,10 +1876,9 @@ |
const Object& arg = Object::Handle(Api::UnwrapHandle(arguments[i])); |
dart_arguments.Add(&arg); |
} |
- const Array& kNoArgumentNames = Array::Handle(); |
- const Object& result = Object::Handle( |
- DartEntry::InvokeStatic(function, dart_arguments, kNoArgumentNames)); |
- return Api::NewLocalHandle(result); |
+ Dart_Handle retval; |
+ InvokeStatic(isolate, function, dart_arguments, &retval); |
+ return retval; |
} |
@@ -1793,11 +1919,9 @@ |
const Object& arg = Object::Handle(Api::UnwrapHandle(arguments[i])); |
dart_arguments.Add(&arg); |
} |
- const Array& kNoArgumentNames = Array::Handle(); |
- const Object& result = Object::Handle( |
- DartEntry::InvokeDynamic( |
- receiver, function, dart_arguments, kNoArgumentNames)); |
- return Api::NewLocalHandle(result); |
+ Dart_Handle retval; |
+ InvokeDynamic(isolate, receiver, function, dart_arguments, &retval); |
+ return retval; |
} |
@@ -1904,10 +2028,8 @@ |
Function& func = Function::Handle(); |
func ^= obj.raw(); |
GrowableArray<const Object*> args; |
- const Array& kNoArgumentNames = Array::Handle(); |
- const Object& result = Object::Handle( |
- DartEntry::InvokeStatic(func, args, kNoArgumentNames)); |
- return Api::NewLocalHandle(result); |
+ InvokeStatic(isolate, func, args, &result); |
+ return result; |
} |
} |
@@ -1953,10 +2075,8 @@ |
Function& func = Function::Handle(); |
func ^= Api::UnwrapHandle(result); |
GrowableArray<const Object*> arguments; |
- const Array& kNoArgumentNames = Array::Handle(); |
- const Object& retval = Object::Handle( |
- DartEntry::InvokeDynamic(object, func, arguments, kNoArgumentNames)); |
- return Api::NewLocalHandle(retval); |
+ InvokeDynamic(isolate, object, func, arguments, &result); |
+ return result; |
} |
@@ -1980,10 +2100,8 @@ |
GrowableArray<const Object*> arguments(1); |
const Object& arg = Object::Handle(Api::UnwrapHandle(value)); |
arguments.Add(&arg); |
- const Array& kNoArgumentNames = Array::Handle(); |
- const Object& retval = Object::Handle( |
- DartEntry::InvokeDynamic(object, func, arguments, kNoArgumentNames)); |
- return Api::NewLocalHandle(retval); |
+ InvokeDynamic(isolate, object, func, arguments, &result); |
+ return result; |
} |
@@ -2147,18 +2265,22 @@ |
} |
const Script& script = Script::Handle(Script::New(url, source, kind)); |
ASSERT(isolate != NULL); |
- const Error& error = Error::Handle(Compiler::Compile(lib, script)); |
- if (error.IsNull()) { |
+ LongJump* base = isolate->long_jump_base(); |
+ LongJump jump; |
+ isolate->set_long_jump_base(&jump); |
+ if (setjmp(*jump.Set()) == 0) { |
+ Compiler::Compile(lib, script); |
*result = Api::NewLocalHandle(lib); |
if (update_lib_status) { |
lib.SetLoaded(); |
} |
} else { |
- *result = Api::NewLocalHandle(error); |
+ SetupErrorResult(result); |
if (update_lib_status) { |
lib.SetLoadError(); |
} |
} |
+ isolate->set_long_jump_base(base); |
} |
@@ -2230,13 +2352,17 @@ |
static void CompileAll(Isolate* isolate, Dart_Handle* result) { |
+ *result = Api::Success(); |
ASSERT(isolate != NULL); |
- const Error& error = Error::Handle(Library::CompileAll()); |
- if (error.IsNull()) { |
- *result = Api::Success(); |
+ LongJump* base = isolate->long_jump_base(); |
+ LongJump jump; |
+ isolate->set_long_jump_base(&jump); |
+ if (setjmp(*jump.Set()) == 0) { |
+ Library::CompileAll(); |
} else { |
- *result = Api::NewLocalHandle(error); |
+ SetupErrorResult(result); |
} |
+ isolate->set_long_jump_base(base); |
} |