From 4b6b2dc9c6f174f91cc59fbb5ada7b46e21be89c Mon Sep 17 00:00:00 2001 From: "peter.rybin@gmail.com" Date: Wed, 24 Feb 2010 19:59:09 +0000 Subject: [PATCH] Implement BlindReference object and provide couple of liveedit-specific structures Review URL: http://codereview.chromium.org/650127 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3943 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/bootstrapper.cc | 13 +++++ src/contexts.h | 2 + src/liveedit.cc | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+) diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc index a7cf421..12efbc1 100644 --- a/src/bootstrapper.cc +++ b/src/bootstrapper.cc @@ -1050,6 +1050,19 @@ bool Genesis::InstallNatives() { script->set_type(Smi::FromInt(Script::TYPE_NATIVE)); global_context()->set_empty_script(*script); } + { + // Builtin function for OpaqueReference -- a JSValue-based object, + // that keeps its field isolated from JavaScript code. It may store + // objects, that JavaScript code may not access. + Handle opaque_reference_fun = + InstallFunction(builtins, "OpaqueReference", JS_VALUE_TYPE, + JSValue::kSize, Top::initial_object_prototype(), + Builtins::Illegal, false); + Handle prototype = + Factory::NewJSObject(Top::object_function(), TENURED); + SetPrototype(opaque_reference_fun, prototype); + global_context()->set_opaque_reference_function(*opaque_reference_fun); + } if (FLAG_natives_file == NULL) { // Without natives file, install default natives. diff --git a/src/contexts.h b/src/contexts.h index 9baf072..98ebc47 100644 --- a/src/contexts.h +++ b/src/contexts.h @@ -95,6 +95,7 @@ enum ContextLookupFlags { call_as_constructor_delegate) \ V(EMPTY_SCRIPT_INDEX, Script, empty_script) \ V(SCRIPT_FUNCTION_INDEX, JSFunction, script_function) \ + V(OPAQUE_REFERENCE_FUNCTION_INDEX, JSFunction, opaque_reference_function) \ V(CONTEXT_EXTENSION_FUNCTION_INDEX, JSFunction, context_extension_function) \ V(OUT_OF_MEMORY_INDEX, Object, out_of_memory) \ V(MAP_CACHE_INDEX, Object, map_cache) \ @@ -216,6 +217,7 @@ class Context: public FixedArray { CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, EMPTY_SCRIPT_INDEX, SCRIPT_FUNCTION_INDEX, + OPAQUE_REFERENCE_FUNCTION_INDEX, CONTEXT_EXTENSION_FUNCTION_INDEX, OUT_OF_MEMORY_INDEX, MAP_CACHE_INDEX, diff --git a/src/liveedit.cc b/src/liveedit.cc index c50e007..f0cd5dd 100644 --- a/src/liveedit.cc +++ b/src/liveedit.cc @@ -84,4 +84,143 @@ bool LiveEditFunctionTracker::IsActive() { return active_function_info_listener != NULL; } +// Unwraps JSValue object, returning its field "value" +static Handle UnwrapJSValue(Handle jsValue) { + return Handle(jsValue->value()); +} + +// Wraps any object into a OpaqueReference, that will hide the object +// from JavaScript. +static Handle WrapInJSValue(Object* object) { + Handle constructor = Top::opaque_reference_function(); + Handle result = + Handle::cast(Factory::NewJSObject(constructor)); + result->set_value(object); + return result; +} + +// Simple helper class that creates more or less typed structures over +// JSArray object. This is an adhoc method of passing structures from C++ +// to JavaScript. +template +class JSArrayBasedStruct { + public: + static S Create() { + Handle array = Factory::NewJSArray(S::kSize_); + return S(array); + } + static S cast(Object* object) { + JSArray* array = JSArray::cast(object); + Handle array_handle(array); + return S(array_handle); + } + explicit JSArrayBasedStruct(Handle array) : array_(array) { + } + Handle GetJSArray() { + return array_; + } + protected: + void SetField(int field_position, Handle value) { + SetElement(array_, field_position, value); + } + void SetSmiValueField(int field_position, int value) { + SetElement(array_, field_position, Handle(Smi::FromInt(value))); + } + Object* GetField(int field_position) { + return array_->GetElement(field_position); + } + int GetSmiValueField(int field_position) { + Object* res = GetField(field_position); + return Smi::cast(res)->value(); + } + private: + Handle array_; +}; + + +// Represents some function compilation details. This structure will be used +// from JavaScript. It contains Code object, which is kept wrapped +// into a BlindReference for sanitizing reasons. +class FunctionInfoWrapper : public JSArrayBasedStruct { + public: + explicit FunctionInfoWrapper(Handle array) + : JSArrayBasedStruct(array) { + } + void SetInitialProperties(Handle name, int start_position, + int end_position, int param_num, int parent_index) { + HandleScope scope; + this->SetField(kFunctionNameOffset_, name); + this->SetSmiValueField(kStartPositionOffset_, start_position); + this->SetSmiValueField(kEndPositionOffset_, end_position); + this->SetSmiValueField(kParamNumOffset_, param_num); + this->SetSmiValueField(kParentIndexOffset_, parent_index); + } + void SetFunctionCode(Handle function_code) { + Handle wrapper = WrapInJSValue(*function_code); + this->SetField(kCodeOffset_, wrapper); + } + void SetScopeInfo(Handle scope_info_array) { + this->SetField(kScopeInfoOffset_, scope_info_array); + } + int GetParentIndex() { + return this->GetSmiValueField(kParentIndexOffset_); + } + Handle GetFunctionCode() { + Handle raw_result = UnwrapJSValue(Handle( + JSValue::cast(this->GetField(kCodeOffset_)))); + return Handle::cast(raw_result); + } + int GetStartPosition() { + return this->GetSmiValueField(kStartPositionOffset_); + } + int GetEndPosition() { + return this->GetSmiValueField(kEndPositionOffset_); + } + + private: + static const int kFunctionNameOffset_ = 0; + static const int kStartPositionOffset_ = 1; + static const int kEndPositionOffset_ = 2; + static const int kParamNumOffset_ = 3; + static const int kCodeOffset_ = 4; + static const int kScopeInfoOffset_ = 5; + static const int kParentIndexOffset_ = 6; + static const int kSize_ = 7; +}; + +// Wraps SharedFunctionInfo along with some of its fields for passing it +// back to JavaScript. SharedFunctionInfo object itself is additionally +// wrapped into BlindReference for sanitizing reasons. +class SharedInfoWrapper : public JSArrayBasedStruct { + public: + explicit SharedInfoWrapper(Handle array) + : JSArrayBasedStruct(array) { + } + + void SetProperties(Handle name, int start_position, int end_position, + Handle info) { + HandleScope scope; + this->SetField(kFunctionNameOffset_, name); + Handle info_holder = WrapInJSValue(*info); + this->SetField(kSharedInfoOffset_, info_holder); + this->SetSmiValueField(kStartPositionOffset_, start_position); + this->SetSmiValueField(kEndPositionOffset_, end_position); + } + Handle GetInfo() { + Object* element = this->GetField(kSharedInfoOffset_); + Handle value_wrapper(JSValue::cast(element)); + Handle raw_result = UnwrapJSValue(value_wrapper); + return Handle::cast(raw_result); + } + + private: + static const int kFunctionNameOffset_ = 0; + static const int kStartPositionOffset_ = 1; + static const int kEndPositionOffset_ = 2; + static const int kSharedInfoOffset_ = 3; + static const int kSize_ = 4; +}; + + + } } // namespace v8::internal -- 2.7.4