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:
parent
e76f06a1e2
commit
4b6b2dc9c6
@ -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.
|
||||
|
@ -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,
|
||||
|
139
src/liveedit.cc
139
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<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
|
||||
|
Loading…
Reference in New Issue
Block a user