From 997df4192a6916568ac9807387783af4cbf6a4b8 Mon Sep 17 00:00:00 2001 From: Toon Schoenmakers Date: Mon, 11 Apr 2016 11:40:23 +0200 Subject: [PATCH] Actually compile again with latest version of v8 This doesn't run as expected just yet, it only compiles for now. An important thing to note here is that you'll need to copy over 2 files from the v8 build directory these being the natives_blob.bin and the snapshot_blob.bin. It requires these to actually startup v8, but we're embedding it inside PHP-JS. --- .gitignore | 2 ++ Makefile | 17 +++++++++-- isolate.cpp | 27 ++++++++++++++++- jsobject.cpp | 4 +-- platform.cpp | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++ platform.h | 8 +++++ 6 files changed, 134 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index fd9c310..6c455bf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ *.o *.so *.d +*_blob.bin +*_blob.h \ No newline at end of file diff --git a/Makefile b/Makefile index 57c5fbb..db7e45a 100644 --- a/Makefile +++ b/Makefile @@ -99,7 +99,8 @@ LINKER_DEPENDENCIES = -lphpcpp -lv8 RM = rm -f CP = cp -f -MKDIR = mkdir -p +MKDIR = mkdir -p +XXD = xxd -i # @@ -112,7 +113,7 @@ MKDIR = mkdir -p SOURCES = $(wildcard *.cpp) OBJECTS = $(SOURCES:%.cpp=%.o) -DEPENDENCIES = $(SOURCES:%.cpp=%.d) +DEPENDENCIES = $(SOURCES:%.cpp=%.d) # @@ -126,10 +127,20 @@ all: ${OBJECTS} ${EXTENSION} # -include ${DEPENDENCIES} +natives_blob.h: natives_blob.bin + ${CP} natives_blob.bin /tmp/natives_blob.bin + ${XXD} /tmp/natives_blob.bin > natives_blob.h + ${RM} /tmp/natives_blob.bin + +snapshot_blob.h: snapshot_blob.bin + ${CP} snapshot_blob.bin /tmp/snapshot_blob.bin + ${XXD} /tmp/snapshot_blob.bin > snapshot_blob.h + ${RM} /tmp/snapshot_blob.bin + ${EXTENSION}: ${OBJECTS} ${LINKER} ${LINKER_FLAGS} -o $@ ${OBJECTS} ${LINKER_DEPENDENCIES} -${OBJECTS}: +${OBJECTS}: snapshot_blob.h natives_blob.h ${COMPILER} ${COMPILER_FLAGS} -o $@ ${@:%.o=%.cpp} install: diff --git a/isolate.cpp b/isolate.cpp index 9d2a08f..5d45b7c 100644 --- a/isolate.cpp +++ b/isolate.cpp @@ -21,6 +21,7 @@ #include "isolate.h" #include #include +#include /** * Start namespace @@ -33,6 +34,24 @@ namespace JS { */ static thread_local std::unique_ptr isolate; +class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { +public: + virtual void* Allocate(size_t length) { + void* data = AllocateUninitialized(length); + return data == NULL ? data : memset(data, 0, length); + } + virtual void* AllocateUninitialized(size_t length) + { + return malloc(length); + } + virtual void Free(void* data, size_t) + { + free(data); + } +}; + +static ArrayBufferAllocator allocator; + /** * Constructor */ @@ -41,8 +60,14 @@ Isolate::Isolate() // create a platform Platform::create(); + // create our parameters + v8::Isolate::CreateParams params; + + // set our custom allocator + params.array_buffer_allocator = &allocator; + // create the actual isolate - _isolate = v8::Isolate::New(); + _isolate = v8::Isolate::New(params); // and enter it _isolate->Enter(); diff --git a/jsobject.cpp b/jsobject.cpp index 99659e6..431f8ed 100644 --- a/jsobject.cpp +++ b/jsobject.cpp @@ -26,6 +26,7 @@ namespace JS { */ JSObject::Iterator::Iterator(Php::Base *base, const Stack &object) : Php::Iterator(base), + _object(object), _position(0) { // create a handle scope, so variables "fall out of scope" and "enter" the context @@ -35,7 +36,6 @@ JSObject::Iterator::Iterator(Php::Base *base, const Stack &object) : // assign variables, this would normally be done inside // the initializer list, but that way we can't create a // HandleScope first and v8 refuses to work without one - _object = object; _keys = _object->GetPropertyNames(); _size = _keys->Length(); } @@ -172,7 +172,7 @@ Php::Value JSObject::__call(const char *name, Php::Parameters ¶ms) // create a handle scope, so variables "fall out of scope", "enter" the context and retrieve the value v8::HandleScope scope(Isolate::get()); v8::Context::Scope context(_object->CreationContext()); - v8::Local function(_object->Get(value(name)).As()); + v8::Local function(_object->Get(value(Php::Value(name))).As()); std::vector> input; // check whether the value actually exists diff --git a/platform.cpp b/platform.cpp index 78d2b73..b0193d9 100644 --- a/platform.cpp +++ b/platform.cpp @@ -34,6 +34,60 @@ static std::mutex mutex; */ static std::atomic platform; +/** + * Execute a v8::Task with a bit of delay, like we want in the CallDelayedOnForegroundThread + * method. + */ +class DelayedTask : public v8::Task +{ +private: + /** + * The underlying task we want to execute + * @var v8::Task + */ + v8::Task *_task; + + /** + * The amount of delay that we want before executing the task + * @var double + */ + double _delay; + +public: + /** + * Constructor + * @param task + * @param delay + */ + DelayedTask(v8::Task *task, double delay) : _task(task), _delay(delay) {} + + /** + * Destructor, we delete the underlying task from here + */ + virtual ~DelayedTask() + { + delete _task; + } + + /** + * The abstract Run method of the v8::Task interface + */ + void Run() override + { + // so first we sleep for '_delay' seconds + std::this_thread::sleep_for(std::chrono::duration(_delay)); + + // and then we run the actual task + _task->Run(); + } +}; + +/** + * Include the dumps of the natives and snapshot blobs + */ +#include "natives_blob.h" +#include "snapshot_blob.h" + /** * Constructor */ @@ -87,6 +141,20 @@ void Platform::create() // initialize the ICU and v8 engine v8::V8::InitializeICU(); + + // create a setup a StartupData object for the natives blob + v8::StartupData natives; + natives.data = (const char*) _tmp_natives_blob_bin; + natives.raw_size = _tmp_natives_blob_bin_len; + v8::V8::SetNativesDataBlob(&natives); + + // create a setup a StartupData object for the snapshot blob + v8::StartupData snapshot; + snapshot.data = (const char*) _tmp_snapshot_blob_bin; + snapshot.raw_size = _tmp_snapshot_blob_bin_len; + v8::V8::SetSnapshotDataBlob(&snapshot); + + // initialize the platform v8::V8::InitializePlatform(result); v8::V8::Initialize(); @@ -238,6 +306,20 @@ void Platform::CallOnForegroundThread(v8::Isolate *isolate, v8::Task *task) */ } +/** + * Schedules a task to be invoked on a foreground thread wrt a specific + * |isolate| after the given number of seconds |delay_in_seconds|. + * Tasks posted for the same isolate should be execute in order of + * scheduling. The definition of "foreground" is opaque to V8. + */ +void Platform::CallDelayedOnForegroundThread(v8::Isolate *isolate, v8::Task *task, double delay_in_seconds) +{ + // we simply call the CallOnBackgroundThread method which will queue our task, but before that + // we turn it into a DelayedTask. The ExpectedRuntime here doesn't matter as our implementation + // of CallOnBackgroundThread doesn't do anything with it anyway + CallOnBackgroundThread(new DelayedTask(task, delay_in_seconds), ExpectedRuntime::kShortRunningTask); +} + /** * Retrieve the monotonically increasing time. The starting point * is not relevant, but it must return at least millisecond-precision diff --git a/platform.h b/platform.h index ea33dfb..503c0aa 100644 --- a/platform.h +++ b/platform.h @@ -114,6 +114,14 @@ class Platform : public v8::Platform */ void CallOnForegroundThread(v8::Isolate *isolate, v8::Task *task) override; + /** + * Schedules a task to be invoked on a foreground thread wrt a specific + * |isolate| after the given number of seconds |delay_in_seconds|. + * Tasks posted for the same isolate should be execute in order of + * scheduling. The definition of "foreground" is opaque to V8. + */ + void CallDelayedOnForegroundThread(v8::Isolate *isolate, v8::Task *task, double delay_in_seconds) override; + /** * Retrieve the monotonically increasing time. The starting point * is not relevant, but it must return at least millisecond-precision