Preliminary Experience of V8 javascript Engine

Source: Internet
Author: User

V8 engine, needless to say, is well-known, so far the fastest js engine.

Such a good thing is too wasteful to be used in a browser, and it is also expected to be used in other places, such as some client development.


This is the beginning.


Download source code

Go to Official Website: https://code.google.com/p/v8/

I like to use git, So download it from here

git clone git://github.com/v8/v8.git v8 && cd v8

Compile

I compiled it for the android platform. It took a long time to record some important points. First you should look at this: http://code.google.com/p/v8/wiki/BuildingWithGYP

The key is

make dependencies
This takes a long time (well, no way. The domestic network speed is not good. I downloaded it several times )...


Then, compile on android (other platforms? So easy, see the document). You can first check the compilation of D8OnAndroid (a js command line on the android platform, but it is useless.

My Own compilation method is cross-compiled.

Cross-compiling

Similar to building with Clang, you can also use a cross-compiler. Just export your toolchain (CXX/LINKEnvironment variables shocould be enough) and compile. For example:

export CXX=/path/to/cross-compile-g++export LINK=/path/to/cross-compile-g++make arm.release

(Compilation is waiting .....)


After that, you can use it.


Use on android

First, create a project (how to create it? This... Find it by yourself), an Activity project, and then create a jni directory under the project directory.

I don't want to talk about how to use ndk. Find it by yourself. I'll focus on it:

1. Copy the header file and Library File

For convenience, I put the header file and library file under the include and lib under jni. The header file can be directly copied from the v8/include folder. The library file is a little more complicated and must be copied:

libicudata.a libicui18n.a libicuuc.a libv8.a libv8_snapshot.a

You can find it in the v8/out directory (Use find, but you cannot remember the specific location) when compilation is missing, the system will report errors that cannot be found)


2. Pay attention to the Android. mk format.

Note the following when writing Android. mk:

1. The reference sequence of the database is very important. The sequence is wrong and symbols cannot be found.

2. Use stl,

The code for Android. mk and Application. mk (required by STL) is as follows, which saves you the trouble of detours for reference.

Android. mk:

LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_CFLAGS += -I$(LOCAL_PATH)/includeLOCAL_LDFLAGS += \    $(LOCAL_PATH)/lib/libv8.a \    $(LOCAL_PATH)/lib/libv8_snapshot.a \    $(LOCAL_PATH)/lib/libicui18n.a \    $(LOCAL_PATH)/lib/libicuuc.a \    $(LOCAL_PATH)/lib/libicudata.a \    /
 
  /android-ndk-r9d//sources/cxx-stl/stlport/libs/armeabi/libstlport_static.aLOCAL_MODULE := jswrapperLOCAL_LDLIBS := -llogLOCAL_SRC_FILES := \    registers.cpp \    JavaScriptContextWrap.cpp \    javautils.cpp \    JsJavaClassProxy.cpp \    javawrap.cpp#sample.cpp sample-jni.cpp \LOCAL_ALLOW_UNDEFINED_SYMBOLS := trueLOCAL_WHOLE_STATIC_LIBRARIES += android_supportinclude $(BUILD_SHARED_LIBRARY)$(call import-module, android/support)
 
(I'm stupid. I can't find the stl link without all the paths. Er, is it another time that God liked me? Do you want to train me ......)

Remember the lib sequence and stl...


Application. mk

APP_CFLAGS += -fexceptionsAPP_CFLAGS += -frttiAPP_STL := stlport_static#gnustl_static

Compile and use ndk-build.


Code Writing

As for the jni part of the code, I will not write it. baidu and google, you know.


Header file? Just use a "v8.h.

1. Initialization

v8::V8::InitializeICU();

(Finished? Yes, that's simple)

2. Create Isolate and Context

    isolate_ = v8::Isolate::New();    isolate_->Enter();    v8::HandleScope handle_scope(isolate_);    v8::Handle
 
   global = v8::ObjectTemplate::New(isolate_);        //create Log object    v8::Handle
  
    log = v8::ObjectTemplate::New(isolate_);    log->Set(v8::String::NewFromUtf8(isolate_, "e"),            v8::FunctionTemplate::New(isolate_, js_func_log_e));    log->Set(v8::String::NewFromUtf8(isolate_, "i"),            v8::FunctionTemplate::New(isolate_, js_func_log_i));    log->Set(v8::String::NewFromUtf8(isolate_, "v"),            v8::FunctionTemplate::New(isolate_, js_func_log_v));    log->Set(v8::String::NewFromUtf8(isolate_, "d"),            v8::FunctionTemplate::New(isolate_, js_func_log_d));    global->Set(v8::String::NewFromUtf8(isolate_, "Log"), log);    //TODO others    global->Set(v8::String::NewFromUtf8(isolate_, "import_java_class"),             v8::FunctionTemplate::New(isolate_, js_func_import_java_class));            context_.Reset(isolate_, v8::Context::New(isolate_, NULL, global));
  
 

The content is a bit Doha. Don't worry. Let me hear it.

First, create a v8: Isolate with v8: Isolate: New (). What is isolate? In fact, I am not quite clear about this. It is like a virtual machine. All javascript objects are on this isolate, and they are not too busy with isolate.

Then you need to call isolate _-> Enter (). Of course, when you want to destroy isolate _-> Leave (), call isolate _-> Leave ().

By the way, v8 is c ++, and the first letter of the member method is uppercase.

Second, we can create an ObjectTemplate. ObjectTemplate is an object template. It corresponds to C ++ and java. You can think of it as a static class and there are a bunch of static methods.

Let's take a look at the last sentence: v8: Context: New (isolate _, NULL, global ). Register a global template. That is to say, if I register a print function in global, I can directly write it in js as follows:

print ("Hi, I\'m from native");

In our example, the sub-ObjectTempl of a Log is registered, and the Log contains the e, I, v, and d methods, which are actually the corresponding android. util. log. e, I, v, d.


The registration method is to call the Set, and the C ++ function pointer needs to be used

v8::FunctionTemplate::New
. You just need to know this. You don't have to go into it (but I don't understand it either)


The above code is actually part of a class. Here there are two member variables:

    v8::Persistent
 
   context_;    v8::Isolate* isolate_;
 
Isolate uses pointers directly, while Context must use Persistent, which is a pointer that can persistently keep objects (to prevent v8 from being garbage collected). Rest is used.:

    context_.Reset(isolate_, v8::Context::New(isolate_, NULL, global));

3. Define a function

Code first: (I use js_func_log_x to implement the public part of functions such as js_func_log_ I)

void js_func_log_x(int level, const v8::FunctionCallbackInfo
 
  & args) {    if (args.Length() == 0) {        return ;    }        //get tag    char szTag[1024] = "";    {        v8::HandleScope handle_scope(args.GetIsolate());        v8::String::Utf8Value str(args[0]);        const char* cstr = ToCString(str);                strcpy(szTag, cstr);    }    char szLog[1024*8] = "";    bool first = true;    int len = 0;    for (int i = 1; i < args.Length(); i++)    {        v8::HandleScope handle_scope(args.GetIsolate());        if (first) {            first = false;        } else {            len += sprintf(szLog + len, " ");        }        v8::String::Utf8Value str(args[i]);        const char* cstr = ToCString(str);        len += sprintf(szLog + len, "%s", cstr);    }    __android_log_print(level, szTag, "%s", szLog);}
 

Args contains parameters and runtime. You must call

        v8::HandleScope handle_scope(args.GetIsolate());

(Why? I don't known ....)

To retrieve a string from the Value, use ToCString, which is also very simple:

static const char* ToCString(const v8::String::Utf8Value& value) {  return *value ? *value : "
 
  ";}
 

The function used by v8 is as follows:

void js_func_log_i(const v8::FunctionCallbackInfo
 
  & args) {    js_func_log_x(ANDROID_LOG_INFO, args);}void js_func_log_v(const v8::FunctionCallbackInfo
  
   & args) {    js_func_log_x(ANDROID_LOG_VERBOSE, args);}void js_func_log_d(const v8::FunctionCallbackInfo
   
    & args) {    js_func_log_x(ANDROID_LOG_DEBUG, args);}void js_func_log_e(const v8::FunctionCallbackInfo
    
     & args) {    js_func_log_x(ANDROID_LOG_ERROR, args);}
    
   
  
 

Now, the first experience is over.


Some important knowledge points 1. Associate an object to Isolate

There can be multiple Isolate objects. If one object is associated with Isolate, how can I find this object from Isolate?

Use Isolate's GetData/SetData

For example

JavaWrapper* JavaWrapper::fromIsolate(Isolate* isolate) {    if (isolate == NULL) {        return NULL;    }    void *data = isolate->GetData(ISOLATE_SLOT_JAVA_WRAPPER);    JavaWrapper* javawrap = reinterpret_cast
 
  (data);        return javawrap && javawrap->isolate_ == isolate ? javawrap : NULL;}JavaWrapper::JavaWrapper(Isolate* isolate):isolate_(isolate){    isolate_->SetData(ISOLATE_SLOT_JAVA_WRAPPER, (void*)this);}
 

2. How to Get parameters of other types from v8: Value

V8: Value is a composite object. We can do this:

    for (int i = 0; i < count; i++) {        HandleScope handle_scope(args.GetIsolate());        Local
 
   v = args[i];        if (v->IsUndefined() || v->IsNull()) {            types[i] = JsJavaClassProxy::NullClass();            values[i] = JsJavaClassProxy::NullObject();            LOGV(" arg(%d) is null\n", i);        } else if (v->IsTrue() || v->IsFalse()) {            types[i] = JsJavaClassProxy::BooleanClass();            jboolean jv = (jboolean)(v->IsTrue() ? true : false);            values[i] = jreflect::ValueOf(env, jv);            LOGV(" arg(%d) is boolean:%d", i, jv);        } else if (v->IsString()) {            types[i] = JsJavaClassProxy::StringClass();            String::Utf8Value str(v);            const char* cstr = ToCString(str);            values[i] = env->NewStringUTF(cstr);            LOGV(" arg(%d) is String:%s", i, cstr);        } else if (v->IsBoolean()) {            types[i] = JsJavaClassProxy::BooleanClass();            jboolean jv = v->ToBoolean()->Value();            values[i] = jreflect::ValueOf(env, jv);            LOGV(" arg(%d) is boolean:%d", i, jv);        } else if (v->IsInt32() || v->IsUint32()) {            types[i] = JsJavaClassProxy::IntClass();            jint jv = v->ToInt32()->Value();            values[i] = jreflect::ValueOf(env, jv);            LOGV(" arg(%d) is int:%d", i, jv);        } else if (v->IsNumber()) {            types[i] = JsJavaClassProxy::DoubleClass();            jdouble jv = v->ToNumber()->Value();            values[i] = jreflect::ValueOf(env, jv);            LOGV(" arg(%d) is double:%f", i, jv);        } /** TODO MORE **/ else {            LOGE("Invalidate Arg type!");            ASSERT(false);        }    }
 
For more information, see v8.h.


Okay. Come here first.




Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.