vendor/v8/src/accessors.cc in mustang-0.0.1 vs vendor/v8/src/accessors.cc in mustang-0.1.0

- old
+ new

@@ -32,21 +32,21 @@ #include "deoptimizer.h" #include "execution.h" #include "factory.h" #include "safepoint-table.h" #include "scopeinfo.h" -#include "top.h" namespace v8 { namespace internal { template <class C> static C* FindInPrototypeChain(Object* obj, bool* found_it) { ASSERT(!*found_it); + Heap* heap = HEAP; while (!Is<C>(obj)) { - if (obj == Heap::null_value()) return NULL; + if (obj == heap->null_value()) return NULL; obj = obj->GetPrototype(); } *found_it = true; return C::cast(obj); } @@ -88,28 +88,29 @@ // The helper function will 'flatten' Number objects. Object* Accessors::FlattenNumber(Object* value) { if (value->IsNumber() || !value->IsJSValue()) return value; JSValue* wrapper = JSValue::cast(value); - ASSERT( - Top::context()->global_context()->number_function()->has_initial_map()); - Map* number_map = - Top::context()->global_context()->number_function()->initial_map(); + ASSERT(Isolate::Current()->context()->global_context()->number_function()-> + has_initial_map()); + Map* number_map = Isolate::Current()->context()->global_context()-> + number_function()->initial_map(); if (wrapper->map() == number_map) return wrapper->value(); return value; } MaybeObject* Accessors::ArraySetLength(JSObject* object, Object* value, void*) { + Isolate* isolate = object->GetIsolate(); value = FlattenNumber(value); // Need to call methods that may trigger GC. - HandleScope scope; + HandleScope scope(isolate); // Protect raw pointers. - Handle<JSObject> object_handle(object); - Handle<Object> value_handle(value); + Handle<JSObject> object_handle(object, isolate); + Handle<Object> value_handle(value, isolate); bool has_exception; Handle<Object> uint32_v = Execution::ToUint32(value_handle, &has_exception); if (has_exception) return Failure::Exception(); Handle<Object> number_v = Execution::ToNumber(value_handle, &has_exception); @@ -124,16 +125,17 @@ return JSArray::cast(object)->SetElementsLength(*uint32_v); } else { // This means one of the object's prototypes is a JSArray and // the object does not have a 'length' property. // Calling SetProperty causes an infinite loop. - return object->SetLocalPropertyIgnoreAttributes(Heap::length_symbol(), - value, NONE); + return object->SetLocalPropertyIgnoreAttributes( + isolate->heap()->length_symbol(), value, NONE); } } - return Top::Throw(*Factory::NewRangeError("invalid_array_length", - HandleVector<Object>(NULL, 0))); + return isolate->Throw( + *isolate->factory()->NewRangeError("invalid_array_length", + HandleVector<Object>(NULL, 0))); } const AccessorDescriptor Accessors::ArrayLength = { ArrayGetLength, @@ -312,19 +314,22 @@ // Accessors::ScriptGetLineEnds // MaybeObject* Accessors::ScriptGetLineEnds(Object* object, void*) { - HandleScope scope; - Handle<Script> script(Script::cast(JSValue::cast(object)->value())); + JSValue* wrapper = JSValue::cast(object); + Isolate* isolate = wrapper->GetIsolate(); + HandleScope scope(isolate); + Handle<Script> script(Script::cast(wrapper->value()), isolate); InitScriptLineEnds(script); ASSERT(script->line_ends()->IsFixedArray()); Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends())); // We do not want anyone to modify this array from JS. - ASSERT(*line_ends == Heap::empty_fixed_array() || - line_ends->map() == Heap::fixed_cow_array_map()); - Handle<JSArray> js_array = Factory::NewJSArrayWithElements(line_ends); + ASSERT(*line_ends == isolate->heap()->empty_fixed_array() || + line_ends->map() == isolate->heap()->fixed_cow_array_map()); + Handle<JSArray> js_array = + isolate->factory()->NewJSArrayWithElements(line_ends); return *js_array; } const AccessorDescriptor Accessors::ScriptLineEnds = { @@ -366,11 +371,11 @@ if (eval_from_shared->script()->IsScript()) { Handle<Script> eval_from_script(Script::cast(eval_from_shared->script())); return *GetScriptWrapper(eval_from_script); } } - return Heap::undefined_value(); + return HEAP->undefined_value(); } const AccessorDescriptor Accessors::ScriptEvalFromScript = { ScriptGetEvalFromScript, @@ -389,11 +394,11 @@ Handle<Script> script(Script::cast(JSValue::cast(object)->value())); // If this is not a script compiled through eval there is no eval position. int compilation_type = Smi::cast(script->compilation_type())->value(); if (compilation_type != Script::COMPILATION_TYPE_EVAL) { - return Heap::undefined_value(); + return HEAP->undefined_value(); } // Get the function from where eval was called and find the source position // from the instruction offset. Handle<Code> code(SharedFunctionInfo::cast( @@ -441,24 +446,25 @@ // Accessors::FunctionPrototype // MaybeObject* Accessors::FunctionGetPrototype(Object* object, void*) { + Heap* heap = Isolate::Current()->heap(); bool found_it = false; JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it); - if (!found_it) return Heap::undefined_value(); + if (!found_it) return heap->undefined_value(); while (!function->should_have_prototype()) { found_it = false; function = FindInPrototypeChain<JSFunction>(object->GetPrototype(), &found_it); // There has to be one because we hit the getter. ASSERT(found_it); } if (!function->has_prototype()) { Object* prototype; - { MaybeObject* maybe_prototype = Heap::AllocateFunctionPrototype(function); + { MaybeObject* maybe_prototype = heap->AllocateFunctionPrototype(function); if (!maybe_prototype->ToObject(&prototype)) return maybe_prototype; } Object* result; { MaybeObject* maybe_result = function->SetPrototype(prototype); if (!maybe_result->ToObject(&result)) return maybe_result; @@ -469,16 +475,17 @@ MaybeObject* Accessors::FunctionSetPrototype(JSObject* object, Object* value, void*) { + Heap* heap = object->GetHeap(); bool found_it = false; JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it); - if (!found_it) return Heap::undefined_value(); + if (!found_it) return heap->undefined_value(); if (!function->should_have_prototype()) { // Since we hit this accessor, object will have no prototype property. - return object->SetLocalPropertyIgnoreAttributes(Heap::prototype_symbol(), + return object->SetLocalPropertyIgnoreAttributes(heap->prototype_symbol(), value, NONE); } if (function->has_initial_map()) { @@ -543,11 +550,11 @@ MaybeObject* Accessors::FunctionGetName(Object* object, void*) { bool found_it = false; JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it); - if (!found_it) return Heap::undefined_value(); + if (!found_it) return HEAP->undefined_value(); return holder->shared()->name(); } const AccessorDescriptor Accessors::FunctionName = { @@ -559,187 +566,24 @@ // // Accessors::FunctionArguments // -static Address SlotAddress(JavaScriptFrame* frame, int slot_index) { - if (slot_index >= 0) { - const int offset = JavaScriptFrameConstants::kLocal0Offset; - return frame->fp() + offset - (slot_index * kPointerSize); - } else { - const int offset = JavaScriptFrameConstants::kReceiverOffset; - return frame->caller_sp() + offset + (slot_index * kPointerSize); - } -} - -// We can't intermix stack decoding and allocations because -// deoptimization infrastracture is not GC safe. -// Thus we build a temporary structure in malloced space. -class SlotRef BASE_EMBEDDED { - public: - enum SlotRepresentation { - UNKNOWN, - TAGGED, - INT32, - DOUBLE, - LITERAL - }; - - SlotRef() - : addr_(NULL), representation_(UNKNOWN) { } - - SlotRef(Address addr, SlotRepresentation representation) - : addr_(addr), representation_(representation) { } - - explicit SlotRef(Object* literal) - : literal_(literal), representation_(LITERAL) { } - - Handle<Object> GetValue() { - switch (representation_) { - case TAGGED: - return Handle<Object>(Memory::Object_at(addr_)); - - case INT32: { - int value = Memory::int32_at(addr_); - if (Smi::IsValid(value)) { - return Handle<Object>(Smi::FromInt(value)); - } else { - return Factory::NewNumberFromInt(value); - } - } - - case DOUBLE: { - double value = Memory::double_at(addr_); - return Factory::NewNumber(value); - } - - case LITERAL: - return literal_; - - default: - UNREACHABLE(); - return Handle<Object>::null(); - } - } - - private: - Address addr_; - Handle<Object> literal_; - SlotRepresentation representation_; -}; - - -static SlotRef ComputeSlotForNextArgument(TranslationIterator* iterator, - DeoptimizationInputData* data, - JavaScriptFrame* frame) { - Translation::Opcode opcode = - static_cast<Translation::Opcode>(iterator->Next()); - - switch (opcode) { - case Translation::BEGIN: - case Translation::FRAME: - // Peeled off before getting here. - break; - - case Translation::ARGUMENTS_OBJECT: - // This can be only emitted for local slots not for argument slots. - break; - - case Translation::REGISTER: - case Translation::INT32_REGISTER: - case Translation::DOUBLE_REGISTER: - case Translation::DUPLICATE: - // We are at safepoint which corresponds to call. All registers are - // saved by caller so there would be no live registers at this - // point. Thus these translation commands should not be used. - break; - - case Translation::STACK_SLOT: { - int slot_index = iterator->Next(); - Address slot_addr = SlotAddress(frame, slot_index); - return SlotRef(slot_addr, SlotRef::TAGGED); - } - - case Translation::INT32_STACK_SLOT: { - int slot_index = iterator->Next(); - Address slot_addr = SlotAddress(frame, slot_index); - return SlotRef(slot_addr, SlotRef::INT32); - } - - case Translation::DOUBLE_STACK_SLOT: { - int slot_index = iterator->Next(); - Address slot_addr = SlotAddress(frame, slot_index); - return SlotRef(slot_addr, SlotRef::DOUBLE); - } - - case Translation::LITERAL: { - int literal_index = iterator->Next(); - return SlotRef(data->LiteralArray()->get(literal_index)); - } - } - - UNREACHABLE(); - return SlotRef(); -} - - - - - -static void ComputeSlotMappingForArguments(JavaScriptFrame* frame, - int inlined_frame_index, - Vector<SlotRef>* args_slots) { - AssertNoAllocation no_gc; - int deopt_index = AstNode::kNoNumber; - DeoptimizationInputData* data = - static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index); - TranslationIterator it(data->TranslationByteArray(), - data->TranslationIndex(deopt_index)->value()); - Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); - ASSERT(opcode == Translation::BEGIN); - int frame_count = it.Next(); - USE(frame_count); - ASSERT(frame_count > inlined_frame_index); - int frames_to_skip = inlined_frame_index; - while (true) { - opcode = static_cast<Translation::Opcode>(it.Next()); - // Skip over operands to advance to the next opcode. - it.Skip(Translation::NumberOfOperandsFor(opcode)); - if (opcode == Translation::FRAME) { - if (frames_to_skip == 0) { - // We reached the frame corresponding to the inlined function - // in question. Process the translation commands for the - // arguments. - // - // Skip the translation command for the receiver. - it.Skip(Translation::NumberOfOperandsFor( - static_cast<Translation::Opcode>(it.Next()))); - // Compute slots for arguments. - for (int i = 0; i < args_slots->length(); ++i) { - (*args_slots)[i] = ComputeSlotForNextArgument(&it, data, frame); - } - return; - } - frames_to_skip--; - } - } - - UNREACHABLE(); -} - - static MaybeObject* ConstructArgumentsObjectForInlinedFunction( JavaScriptFrame* frame, Handle<JSFunction> inlined_function, int inlined_frame_index) { + Factory* factory = Isolate::Current()->factory(); int args_count = inlined_function->shared()->formal_parameter_count(); ScopedVector<SlotRef> args_slots(args_count); - ComputeSlotMappingForArguments(frame, inlined_frame_index, &args_slots); + SlotRef::ComputeSlotMappingForArguments(frame, + inlined_frame_index, + &args_slots); Handle<JSObject> arguments = - Factory::NewArgumentsObject(inlined_function, args_count); - Handle<FixedArray> array = Factory::NewFixedArray(args_count); + factory->NewArgumentsObject(inlined_function, args_count); + Handle<FixedArray> array = factory->NewFixedArray(args_count); for (int i = 0; i < args_count; ++i) { Handle<Object> value = args_slots[i].GetValue(); array->set(i, *value); } arguments->set_elements(*array); @@ -748,15 +592,16 @@ return *arguments; } MaybeObject* Accessors::FunctionGetArguments(Object* object, void*) { - HandleScope scope; + Isolate* isolate = Isolate::Current(); + HandleScope scope(isolate); bool found_it = false; JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it); - if (!found_it) return Heap::undefined_value(); - Handle<JSFunction> function(holder); + if (!found_it) return isolate->heap()->undefined_value(); + Handle<JSFunction> function(holder, isolate); // Find the top invocation of the function by traversing frames. List<JSFunction*> functions(2); for (JavaScriptFrameIterator it; !it.done(); it.Advance()) { JavaScriptFrame* frame = it.frame(); @@ -774,13 +619,13 @@ } if (!frame->is_optimized()) { // If there is an arguments variable in the stack, we return that. Handle<SerializedScopeInfo> info(function->shared()->scope_info()); - int index = info->StackSlotIndex(Heap::arguments_symbol()); + int index = info->StackSlotIndex(isolate->heap()->arguments_symbol()); if (index >= 0) { - Handle<Object> arguments(frame->GetExpression(index)); + Handle<Object> arguments(frame->GetExpression(index), isolate); if (!arguments->IsArgumentsMarker()) return *arguments; } } // If there is no arguments variable in the stack or we have an @@ -789,14 +634,14 @@ it.AdvanceToArgumentsFrame(); frame = it.frame(); // Get the number of arguments and construct an arguments object // mirror for the right frame. - const int length = frame->GetProvidedParametersCount(); - Handle<JSObject> arguments = Factory::NewArgumentsObject(function, - length); - Handle<FixedArray> array = Factory::NewFixedArray(length); + const int length = frame->ComputeParametersCount(); + Handle<JSObject> arguments = isolate->factory()->NewArgumentsObject( + function, length); + Handle<FixedArray> array = isolate->factory()->NewFixedArray(length); // Copy the parameters to the arguments object. ASSERT(array->length() == length); for (int i = 0; i < length; i++) array->set(i, frame->GetParameter(i)); arguments->set_elements(*array); @@ -806,11 +651,11 @@ } functions.Rewind(0); } // No frame corresponding to the given function found. Return null. - return Heap::null_value(); + return isolate->heap()->null_value(); } const AccessorDescriptor Accessors::FunctionArguments = { FunctionGetArguments, @@ -822,17 +667,31 @@ // // Accessors::FunctionCaller // +static MaybeObject* CheckNonStrictCallerOrThrow( + Isolate* isolate, + JSFunction* caller) { + DisableAssertNoAllocation enable_allocation; + if (caller->shared()->strict_mode()) { + return isolate->Throw( + *isolate->factory()->NewTypeError("strict_caller", + HandleVector<Object>(NULL, 0))); + } + return caller; +} + + MaybeObject* Accessors::FunctionGetCaller(Object* object, void*) { - HandleScope scope; + Isolate* isolate = Isolate::Current(); + HandleScope scope(isolate); AssertNoAllocation no_alloc; bool found_it = false; JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it); - if (!found_it) return Heap::undefined_value(); - Handle<JSFunction> function(holder); + if (!found_it) return isolate->heap()->undefined_value(); + Handle<JSFunction> function(holder, isolate); List<JSFunction*> functions(2); for (JavaScriptFrameIterator it; !it.done(); it.Advance()) { JavaScriptFrame* frame = it.frame(); frame->GetFunctions(&functions); @@ -841,30 +700,30 @@ // Once we have found the frame, we need to go to the caller // frame. This may require skipping through a number of top-level // frames, e.g. frames for scripts not functions. if (i > 0) { ASSERT(!functions[i - 1]->shared()->is_toplevel()); - return functions[i - 1]; + return CheckNonStrictCallerOrThrow(isolate, functions[i - 1]); } else { for (it.Advance(); !it.done(); it.Advance()) { frame = it.frame(); functions.Rewind(0); frame->GetFunctions(&functions); if (!functions.last()->shared()->is_toplevel()) { - return functions.last(); + return CheckNonStrictCallerOrThrow(isolate, functions.last()); } ASSERT(functions.length() == 1); } - if (it.done()) return Heap::null_value(); + if (it.done()) return isolate->heap()->null_value(); break; } } } functions.Rewind(0); } // No frame corresponding to the given function found. Return null. - return Heap::null_value(); + return isolate->heap()->null_value(); } const AccessorDescriptor Accessors::FunctionCaller = { FunctionGetCaller,