Implement BlindReference object and provide couple of liveedit-specific structures
authorpeter.rybin@gmail.com <peter.rybin@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 24 Feb 2010 19:59:09 +0000 (19:59 +0000)
committerpeter.rybin@gmail.com <peter.rybin@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 24 Feb 2010 19:59:09 +0000 (19:59 +0000)
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
src/contexts.h
src/liveedit.cc

index a7cf421..12efbc1 100644 (file)
@@ -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<JSFunction> opaque_reference_fun =
+        InstallFunction(builtins, "OpaqueReference", JS_VALUE_TYPE,
+                        JSValue::kSize, Top::initial_object_prototype(),
+                        Builtins::Illegal, false);
+    Handle<JSObject> 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.
index 9baf072..98ebc47 100644 (file)
@@ -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,
index c50e007..f0cd5dd 100644 (file)
@@ -84,4 +84,143 @@ bool LiveEditFunctionTracker::IsActive() {
   return active_function_info_listener != NULL;
 }
 
+// Unwraps JSValue object, returning its field "value"
+static Handle<Object> UnwrapJSValue(Handle<JSValue> jsValue) {
+  return Handle<Object>(jsValue->value());
+}
+
+// Wraps any object into a OpaqueReference, that will hide the object
+// from JavaScript.
+static Handle<JSValue> WrapInJSValue(Object* object) {
+  Handle<JSFunction> constructor = Top::opaque_reference_function();
+  Handle<JSValue> result =
+      Handle<JSValue>::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<typename S>
+class JSArrayBasedStruct {
+ public:
+  static S Create() {
+    Handle<JSArray> array = Factory::NewJSArray(S::kSize_);
+    return S(array);
+  }
+  static S cast(Object* object) {
+    JSArray* array = JSArray::cast(object);
+    Handle<JSArray> array_handle(array);
+    return S(array_handle);
+  }
+  explicit JSArrayBasedStruct(Handle<JSArray> array) : array_(array) {
+  }
+  Handle<JSArray> GetJSArray() {
+    return array_;
+  }
+ protected:
+  void SetField(int field_position, Handle<Object> value) {
+    SetElement(array_, field_position, value);
+  }
+  void SetSmiValueField(int field_position, int value) {
+    SetElement(array_, field_position, Handle<Smi>(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<JSArray> 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<FunctionInfoWrapper> {
+ public:
+  explicit FunctionInfoWrapper(Handle<JSArray> array)
+      : JSArrayBasedStruct<FunctionInfoWrapper>(array) {
+  }
+  void SetInitialProperties(Handle<String> 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<Code> function_code) {
+    Handle<JSValue> wrapper = WrapInJSValue(*function_code);
+    this->SetField(kCodeOffset_, wrapper);
+  }
+  void SetScopeInfo(Handle<JSArray> scope_info_array) {
+    this->SetField(kScopeInfoOffset_, scope_info_array);
+  }
+  int GetParentIndex() {
+    return this->GetSmiValueField(kParentIndexOffset_);
+  }
+  Handle<Code> GetFunctionCode() {
+    Handle<Object> raw_result = UnwrapJSValue(Handle<JSValue>(
+        JSValue::cast(this->GetField(kCodeOffset_))));
+    return Handle<Code>::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<SharedInfoWrapper> {
+ public:
+  explicit SharedInfoWrapper(Handle<JSArray> array)
+      : JSArrayBasedStruct<SharedInfoWrapper>(array) {
+  }
+
+  void SetProperties(Handle<String> name, int start_position, int end_position,
+                     Handle<SharedFunctionInfo> info) {
+    HandleScope scope;
+    this->SetField(kFunctionNameOffset_, name);
+    Handle<JSValue> info_holder = WrapInJSValue(*info);
+    this->SetField(kSharedInfoOffset_, info_holder);
+    this->SetSmiValueField(kStartPositionOffset_, start_position);
+    this->SetSmiValueField(kEndPositionOffset_, end_position);
+  }
+  Handle<SharedFunctionInfo> GetInfo() {
+    Object* element = this->GetField(kSharedInfoOffset_);
+    Handle<JSValue> value_wrapper(JSValue::cast(element));
+    Handle<Object> raw_result = UnwrapJSValue(value_wrapper);
+    return Handle<SharedFunctionInfo>::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