V8 Android,创建上下文导致 ASSERT ... CHECK(object->IsJSFunction()) 失败
我已经成功地将 Android 的 V8 javascript 引擎编译为静态库 (libv8arm.a),并且可以将其静态链接到我的 Android 本机 C++ 应用程序(使用 ndk-r5b)。
在 Android 上,当创建 V8 上下文时,我会得到此运行时断言 ...
// 初始化 V8 上下文。
本地全局变量 = ObjectTemplate::New();
上下文 = 上下文::New( NULL, 全局变量 );
v8/src/objects-inl.h 中的致命错误,第 1581 行
CHECK(object->IsJSFunction()) 失败
当我将 V8 嵌入到我的应用程序的 MacOSX 版本中时,一切运行正常,我可以毫无问题地执行 javascript。我花了很多时间来比较代码,并查看 gcc 命令行参数来为 Android 构建 V8。我被困住了,差点把 V8 代码拆成碎片才能弄清楚。
有谁知道 V8 运行时初始化需要哪些东西才能通过 Context::New() 断言?
谢谢。
更新:
我试图通过修改 CAST_ACCESSOR 宏来解决这个问题...
extern int __cast_accessor_count /* = 0 */;
// in the cpp file where Context::New() is called
//namespace v8 { namespace internal {
//int __cast_accessor_count = 0;
//}; };
#define CAST_ACCESSOR(type) \
type* type::cast(Object* object) { \
__cast_accessor_count++; \
if( !object->Is##type() ) { OS::Print( "CAST_ACCESSOR %d %s\n", __cast_accessor_count, #type ); object->ShortPrint(); } \
ASSERT(object->Is##type()); \
return reinterpret_cast<type*>(object); \
}
...并在调用 Context::New() 之前和之后打印值...
printf( "__cast_accessor_count=%d\n", v8::internal::__cast_accessor_count );
// Create a new context.
Persistent<Context> context = Context::New();
printf( "__cast_accessor_count=%d\n", v8::internal::__cast_accessor_count );
在我的 MacOSX 测试应用程序中,输出
__cast_accessor_count=0
(gdb) continue
__cast_accessor_count=272875
在 Android 上是之前的输出 通过 V8 代码搜索断言
__cast_accessor_count=0
CAST_ACCESSOR 101980 JSFunction
0x486c4135 <undefined>
以查找 object->ShortPrint() 输出“未定义”的位置,我发现了这个...
case ODDBALL_TYPE: {
if (IsUndefined())
accumulator->Add("<undefined>");
我想知道 ODDBALL_TYPE 是否由代码生成器发出,并且它对于 IA32 程序集有所不同和ARM汇编。这可能解释了每个平台上不同的初始化。
更新2:
终于得到了一个有效的调用堆栈...
0x001e3b4e: PAUL_DEBUG_BREAK + 0x002e
0x0023d916:_ZN2v88internal10JSFunction4castEPNS0_6ObjectE + 0x0056
0x00251594:_ZN2v88internal7Genesis17InstallJSBuiltinsENS0_6HandleINS0_16JSBuiltinsObjectEEE + 0x0048
0x00250e6c:_ZN2v88internal7Genesis14InstallNativesEv + 0x05e8
0x0025241c:_ZN2v88internal7GenesisC1ENS0_6HandleINS0_6ObjectEEENS_6HandleINS_14ObjectTemplateEEEPNS_22ExtensionConfigurationE + 0x01c4
0x0024ed5a:_ZN2v88internal12Bootstrapper17CreateEnvironmentENS0_6HandleINS0_6ObjectEEENS_6HandleINS_14ObjectTemplateEEEPNS_22ExtensionConfigurationE + 0x0022
0x00247a46:_ZN2v87Context3NewEPNS_22ExtensionConfigurationENS_6HandleINS_14ObjectTemplateEEENS3_INS_5ValueEEE + 0x017e
0x001e3c02: _ZN16JavascriptEngine4InitEv + 0x007a
arm-eabi-c++filt
v8::internal::JSFunction::cast(v8::internal::Object*)
v8::internal::Genesis::InstallJSBuiltins(v8::internal::Handle<v8::internal::JSBuiltinsObject>)
v8::internal::Genesis::InstallNatives()
v8::internal::Genesis::Genesis(v8::internal::Handle<v8::internal::Object>, v8::Handle<v8::ObjectTemplate>, v8::ExtensionConfiguration*)
v8::internal::Bootstrapper::CreateEnvironment(v8::internal::Handle<v8::internal::Object>, v8::Handle<v8::ObjectTemplate>, v8::ExtensionConfiguration*)
v8::Context::New(v8::ExtensionConfiguration*, v8::Handle<v8::ObjectTemplate>, v8::Handle<v8::Value>)
JavascriptEngine::Init()
I've successfully compiled V8 javascript engine for Android as a static lib (libv8arm.a), and I can statically link it into my android native C++ app (using ndk-r5b).
On Android, when the V8 context is created I get this runtime assert ...
// Initialize the V8 context.
Local globals = ObjectTemplate::New();
context = Context::New( NULL, globals );
Fatal error in v8/src/objects-inl.h, line 1581
CHECK(object->IsJSFunction()) failed
When I embed V8 into the MacOSX version of my app, everything runs fine and I can execute javascript without any problems. I've spent many hours diffing code and also looking at gcc command line args for building V8 for Android. I'm stuck, and very near to hacking V8 code to pieces to figure it out.
Does anyone know what things V8 runtime initialization needs to get past Context::New() asserting?
Thanks.
UPDATE:
I'm attempting to trap this problem by modifying the CAST_ACCESSOR macro...
extern int __cast_accessor_count /* = 0 */;
// in the cpp file where Context::New() is called
//namespace v8 { namespace internal {
//int __cast_accessor_count = 0;
//}; };
#define CAST_ACCESSOR(type) \
type* type::cast(Object* object) { \
__cast_accessor_count++; \
if( !object->Is##type() ) { OS::Print( "CAST_ACCESSOR %d %s\n", __cast_accessor_count, #type ); object->ShortPrint(); } \
ASSERT(object->Is##type()); \
return reinterpret_cast<type*>(object); \
}
... and printing the value before and after calling Context::New() ...
printf( "__cast_accessor_count=%d\n", v8::internal::__cast_accessor_count );
// Create a new context.
Persistent<Context> context = Context::New();
printf( "__cast_accessor_count=%d\n", v8::internal::__cast_accessor_count );
in my MacOSX test app, the output is
__cast_accessor_count=0
(gdb) continue
__cast_accessor_count=272875
on Android the output before hitting the assert is
__cast_accessor_count=0
CAST_ACCESSOR 101980 JSFunction
0x486c4135 <undefined>
searched through the V8 code to find where object->ShortPrint() is outputing "undefined" and I found this...
case ODDBALL_TYPE: {
if (IsUndefined())
accumulator->Add("<undefined>");
I'm wondering if ODDBALL_TYPE is emitted by the codegen, and its different for IA32 assembly and ARM assembly. That might explain different initialization on each platform.
UPDATE2:
finally got a valid callstack...
0x001e3b4e: PAUL_DEBUG_BREAK + 0x002e
0x0023d916:_ZN2v88internal10JSFunction4castEPNS0_6ObjectE + 0x0056
0x00251594:_ZN2v88internal7Genesis17InstallJSBuiltinsENS0_6HandleINS0_16JSBuiltinsObjectEEE + 0x0048
0x00250e6c:_ZN2v88internal7Genesis14InstallNativesEv + 0x05e8
0x0025241c:_ZN2v88internal7GenesisC1ENS0_6HandleINS0_6ObjectEEENS_6HandleINS_14ObjectTemplateEEEPNS_22ExtensionConfigurationE + 0x01c4
0x0024ed5a:_ZN2v88internal12Bootstrapper17CreateEnvironmentENS0_6HandleINS0_6ObjectEEENS_6HandleINS_14ObjectTemplateEEEPNS_22ExtensionConfigurationE + 0x0022
0x00247a46:_ZN2v87Context3NewEPNS_22ExtensionConfigurationENS_6HandleINS_14ObjectTemplateEEENS3_INS_5ValueEEE + 0x017e
0x001e3c02: _ZN16JavascriptEngine4InitEv + 0x007a
arm-eabi-c++filt
v8::internal::JSFunction::cast(v8::internal::Object*)
v8::internal::Genesis::InstallJSBuiltins(v8::internal::Handle<v8::internal::JSBuiltinsObject>)
v8::internal::Genesis::InstallNatives()
v8::internal::Genesis::Genesis(v8::internal::Handle<v8::internal::Object>, v8::Handle<v8::ObjectTemplate>, v8::ExtensionConfiguration*)
v8::internal::Bootstrapper::CreateEnvironment(v8::internal::Handle<v8::internal::Object>, v8::Handle<v8::ObjectTemplate>, v8::ExtensionConfiguration*)
v8::Context::New(v8::ExtensionConfiguration*, v8::Handle<v8::ObjectTemplate>, v8::Handle<v8::Value>)
JavascriptEngine::Init()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
Library.cc 就是答案。
在 android 上,我使用的是为 macosx 构建生成的libraries.cc 文件。我通过使用 js2c.py 工具为 android 生成新的libraries.cc 文件修复了 android 上的问题。
libraries.cc is the answer.
On android, I was using the libraries.cc file which was generated for the macosx build. I fixed the problem on android by using the js2c.py tool to generate a new libraries.cc file for android.