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
This commit is contained in:
peter.rybin@gmail.com 2010-02-24 19:59:09 +00:00
parent e76f06a1e2
commit 4b6b2dc9c6
3 changed files with 154 additions and 0 deletions

View 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.

View 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,

View 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