Disallow dereferencing deferred handles when generating optimized code.

R=mvstanton@chromium.org
BUG=

Review URL: https://chromiumcodereview.appspot.com/14403015

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14388 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
yangguo@chromium.org 2013-04-23 09:23:07 +00:00
parent d352df8131
commit 28bbe46a98
34 changed files with 400 additions and 218 deletions

View File

@ -305,16 +305,20 @@ void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
// See assembler-arm-inl.h for inlined constructors
Operand::Operand(Handle<Object> handle) {
#ifdef DEBUG
Isolate* isolate = Isolate::Current();
#endif
ALLOW_HANDLE_DEREF(isolate, "using and embedding raw address");
rm_ = no_reg;
// Verify all Objects referred by code are NOT in new space.
Object* obj = *handle;
ASSERT(!HEAP->InNewSpace(obj));
ASSERT(!isolate->heap()->InNewSpace(obj));
if (obj->IsHeapObject()) {
imm32_ = reinterpret_cast<intptr_t>(handle.location());
rmode_ = RelocInfo::EMBEDDED_OBJECT;
} else {
// no relocation needed
imm32_ = reinterpret_cast<intptr_t>(obj);
imm32_ = reinterpret_cast<intptr_t>(obj);
rmode_ = RelocInfo::NONE32;
}
}

View File

@ -1854,7 +1854,6 @@ class LInvokeFunction: public LTemplateInstruction<1, 1, 0> {
virtual void PrintDataTo(StringStream* stream);
int arity() const { return hydrogen()->argument_count() - 1; }
Handle<JSFunction> known_function() { return hydrogen()->known_function(); }
};
@ -1922,7 +1921,6 @@ class LCallKnownGlobal: public LTemplateInstruction<1, 0, 0> {
virtual void PrintDataTo(StringStream* stream);
Handle<JSFunction> target() const { return hydrogen()->target(); }
int arity() const { return hydrogen()->argument_count() - 1; }
};
@ -2499,8 +2497,6 @@ class LFunctionLiteral: public LTemplateInstruction<1, 0, 0> {
public:
DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function-literal")
DECLARE_HYDROGEN_ACCESSOR(FunctionLiteral)
Handle<SharedFunctionInfo> shared_info() { return hydrogen()->shared_info(); }
};

View File

@ -595,7 +595,7 @@ void LCodeGen::WriteTranslation(LEnvironment* environment,
pushed_arguments_index,
pushed_arguments_count);
bool has_closure_id = !info()->closure().is_null() &&
*info()->closure() != *environment->closure();
!info()->closure().is_identical_to(environment->closure());
int closure_id = has_closure_id
? DefineDeoptimizationLiteral(environment->closure())
: Translation::kSelfLiteralId;
@ -911,10 +911,13 @@ void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
Handle<FixedArray> literals =
factory()->NewFixedArray(deoptimization_literals_.length(), TENURED);
for (int i = 0; i < deoptimization_literals_.length(); i++) {
literals->set(i, *deoptimization_literals_[i]);
{ ALLOW_HANDLE_DEREF(isolate(),
"copying a ZoneList of handles into a FixedArray");
for (int i = 0; i < deoptimization_literals_.length(); i++) {
literals->set(i, *deoptimization_literals_[i]);
}
data->SetLiteralArray(*literals);
}
data->SetLiteralArray(*literals);
data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id().ToInt()));
data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_));
@ -1901,6 +1904,7 @@ void LCodeGen::DoConstantD(LConstantD* instr) {
void LCodeGen::DoConstantT(LConstantT* instr) {
Handle<Object> value = instr->value();
ALLOW_HANDLE_DEREF(isolate(), "smi check");
if (value->IsSmi()) {
__ mov(ToRegister(instr->result()), Operand(value));
} else {
@ -3705,12 +3709,15 @@ void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) {
void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
int formal_parameter_count,
int arity,
LInstruction* instr,
CallKind call_kind,
R1State r1_state) {
bool can_invoke_directly = !function->NeedsArgumentsAdaption() ||
function->shared()->formal_parameter_count() == arity;
bool dont_adapt_arguments =
formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel;
bool can_invoke_directly =
dont_adapt_arguments || formal_parameter_count == arity;
LPointerMap* pointers = instr->pointer_map();
RecordPosition(pointers->position());
@ -3725,7 +3732,7 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
// Set r0 to arguments count if adaption is not needed. Assumes that r0
// is available to write to at this point.
if (!function->NeedsArgumentsAdaption()) {
if (dont_adapt_arguments) {
__ mov(r0, Operand(arity));
}
@ -3739,7 +3746,9 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
} else {
SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
ParameterCount count(arity);
__ InvokeFunction(function, count, CALL_FUNCTION, generator, call_kind);
ParameterCount expected(formal_parameter_count);
__ InvokeFunction(
function, expected, count, CALL_FUNCTION, generator, call_kind);
}
// Restore context.
@ -3749,7 +3758,8 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
ASSERT(ToRegister(instr->result()).is(r0));
CallKnownFunction(instr->function(),
CallKnownFunction(instr->hydrogen()->function(),
instr->hydrogen()->formal_parameter_count(),
instr->arity(),
instr,
CALL_AS_METHOD,
@ -4121,7 +4131,8 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
ASSERT(ToRegister(instr->function()).is(r1));
ASSERT(instr->HasPointerMap());
if (instr->known_function().is_null()) {
Handle<JSFunction> known_function = instr->hydrogen()->known_function();
if (known_function.is_null()) {
LPointerMap* pointers = instr->pointer_map();
RecordPosition(pointers->position());
SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
@ -4129,7 +4140,8 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
__ InvokeFunction(r1, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
} else {
CallKnownFunction(instr->known_function(),
CallKnownFunction(known_function,
instr->hydrogen()->formal_parameter_count(),
instr->arity(),
instr,
CALL_AS_METHOD,
@ -4189,7 +4201,8 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
ASSERT(ToRegister(instr->result()).is(r0));
CallKnownFunction(instr->target(),
CallKnownFunction(instr->hydrogen()->target(),
instr->hydrogen()->formal_parameter_count(),
instr->arity(),
instr,
CALL_AS_FUNCTION,
@ -5209,6 +5222,7 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
Register reg = ToRegister(instr->value());
Handle<JSFunction> target = instr->hydrogen()->target();
ALLOW_HANDLE_DEREF(isolate(), "smi check");
if (isolate()->heap()->InNewSpace(*target)) {
Register reg = ToRegister(instr->value());
Handle<JSGlobalPropertyCell> cell =
@ -5350,16 +5364,12 @@ void LCodeGen::DoAllocateObject(LAllocateObject* instr) {
Register scratch = ToRegister(instr->temp());
Register scratch2 = ToRegister(instr->temp2());
Handle<JSFunction> constructor = instr->hydrogen()->constructor();
Handle<Map> initial_map(constructor->initial_map());
Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map();
int instance_size = initial_map->instance_size();
ASSERT(initial_map->pre_allocated_property_fields() +
initial_map->unused_property_fields() -
initial_map->inobject_properties() == 0);
// Allocate memory for the object. The initial map might change when
// the constructor's prototype changes, but instance size and property
// counts remain unchanged (if slack tracking finished).
ASSERT(!constructor->shared()->IsInobjectSlackTrackingInProgress());
__ Allocate(instance_size, result, scratch, scratch2, deferred->entry(),
TAG_OBJECT);
@ -5394,8 +5404,7 @@ void LCodeGen::DoAllocateObject(LAllocateObject* instr) {
void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) {
Register result = ToRegister(instr->result());
Handle<JSFunction> constructor = instr->hydrogen()->constructor();
Handle<Map> initial_map(constructor->initial_map());
Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map();
int instance_size = initial_map->instance_size();
// TODO(3095996): Get rid of this. For now, we need to make the
@ -5478,7 +5487,7 @@ void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
Handle<FixedArray> literals(instr->environment()->closure()->literals());
Handle<FixedArray> literals = instr->hydrogen()->literals();
ElementsKind boilerplate_elements_kind =
instr->hydrogen()->boilerplate_elements_kind();
AllocationSiteMode allocation_site_mode =
@ -5533,7 +5542,7 @@ void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) {
Handle<FixedArray> literals(instr->environment()->closure()->literals());
Handle<FixedArray> literals = instr->hydrogen()->literals();
Handle<FixedArray> constant_properties =
instr->hydrogen()->constant_properties();
@ -5547,7 +5556,7 @@ void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) {
__ mov(r0, Operand(Smi::FromInt(flags)));
// Pick the right runtime function or stub to call.
int properties_count = constant_properties->length() / 2;
int properties_count = instr->hydrogen()->constant_properties_length() / 2;
if (instr->hydrogen()->depth() > 1) {
__ Push(r3, r2, r1, r0);
CallRuntime(Runtime::kCreateObjectLiteral, 4, instr);
@ -5616,19 +5625,17 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
// Use the fast case closure allocation code that allocates in new
// space for nested functions that don't need literals cloning.
Handle<SharedFunctionInfo> shared_info = instr->shared_info();
bool pretenure = instr->hydrogen()->pretenure();
if (!pretenure && shared_info->num_literals() == 0) {
FastNewClosureStub stub(shared_info->language_mode(),
shared_info->is_generator());
__ mov(r1, Operand(shared_info));
if (!pretenure && instr->hydrogen()->has_no_literals()) {
FastNewClosureStub stub(instr->hydrogen()->language_mode(),
instr->hydrogen()->is_generator());
__ mov(r1, Operand(instr->hydrogen()->shared_info()));
__ push(r1);
CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
} else {
__ mov(r2, Operand(shared_info));
__ mov(r1, Operand(pretenure
? factory()->true_value()
: factory()->false_value()));
__ mov(r2, Operand(instr->hydrogen()->shared_info()));
__ mov(r1, Operand(pretenure ? factory()->true_value()
: factory()->false_value()));
__ Push(cp, r2, r1);
CallRuntime(Runtime::kNewClosure, 3, instr);
}

View File

@ -276,6 +276,7 @@ class LCodeGen BASE_EMBEDDED {
// Generate a direct call to a known function. Expects the function
// to be in r1.
void CallKnownFunction(Handle<JSFunction> function,
int formal_parameter_count,
int arity,
LInstruction* instr,
CallKind call_kind,

View File

@ -74,6 +74,7 @@ void MacroAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode,
Condition cond) {
ASSERT(RelocInfo::IsCodeTarget(rmode));
// 'code' is always generated ARM code, never THUMB code
ALLOW_HANDLE_DEREF(isolate(), "embedding raw address");
Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond);
}
@ -162,6 +163,7 @@ int MacroAssembler::CallSize(Handle<Code> code,
RelocInfo::Mode rmode,
TypeFeedbackId ast_id,
Condition cond) {
ALLOW_HANDLE_DEREF(isolate(), "using raw address");
return CallSize(reinterpret_cast<Address>(code.location()), rmode, cond);
}
@ -179,6 +181,7 @@ void MacroAssembler::Call(Handle<Code> code,
rmode = RelocInfo::CODE_TARGET_WITH_ID;
}
// 'code' is always generated ARM code, never THUMB code
ALLOW_HANDLE_DEREF(isolate(), "embedding raw address");
Call(reinterpret_cast<Address>(code.location()), rmode, cond, mode);
}
@ -395,6 +398,7 @@ void MacroAssembler::StoreRoot(Register source,
void MacroAssembler::LoadHeapObject(Register result,
Handle<HeapObject> object) {
ALLOW_HANDLE_DEREF(isolate(), "using raw address");
if (isolate()->heap()->InNewSpace(*object)) {
Handle<JSGlobalPropertyCell> cell =
isolate()->factory()->NewJSGlobalPropertyCell(object);
@ -1227,6 +1231,7 @@ void MacroAssembler::InvokeFunction(Register fun,
void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
const ParameterCount& expected,
const ParameterCount& actual,
InvokeFlag flag,
const CallWrapper& call_wrapper,
@ -1238,7 +1243,6 @@ void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
LoadHeapObject(r1, function);
ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
ParameterCount expected(function->shared()->formal_parameter_count());
// We call indirectly through the code field in the function to
// allow recompilation to take effect without changing any of the
// call sites.

View File

@ -178,6 +178,7 @@ class MacroAssembler: public Assembler {
void LoadHeapObject(Register dst, Handle<HeapObject> object);
void LoadObject(Register result, Handle<Object> object) {
ALLOW_HANDLE_DEREF(isolate(), "heap object check");
if (object->IsHeapObject()) {
LoadHeapObject(result, Handle<HeapObject>::cast(object));
} else {
@ -621,6 +622,7 @@ class MacroAssembler: public Assembler {
CallKind call_kind);
void InvokeFunction(Handle<JSFunction> function,
const ParameterCount& expected,
const ParameterCount& actual,
InvokeFlag flag,
const CallWrapper& call_wrapper,

View File

@ -954,7 +954,8 @@ class CallInterceptorCompiler BASE_EMBEDDED {
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(optimization.constant_function(), arguments_,
Handle<JSFunction> fun = optimization.constant_function();
__ InvokeFunction(fun, ParameterCount(fun), arguments_,
JUMP_FUNCTION, NullCallWrapper(), call_kind);
}
@ -2084,8 +2085,8 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
__ bind(&slow);
__ InvokeFunction(
function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
__ InvokeFunction(function, ParameterCount(function), arguments(),
JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
__ bind(&miss);
// r2: function name.
@ -2195,8 +2196,8 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
__ bind(&slow);
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
__ InvokeFunction(
function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
__ InvokeFunction(function, ParameterCount(function), arguments(),
JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
__ bind(&miss);
// r2: function name.
@ -2294,8 +2295,8 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
__ bind(&slow);
__ InvokeFunction(
function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
__ InvokeFunction(function, ParameterCount(function), arguments(),
JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
__ bind(&miss);
// r2: function name.
@ -2469,8 +2470,8 @@ void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) {
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(
function, arguments(), JUMP_FUNCTION, NullCallWrapper(), call_kind);
__ InvokeFunction(function, ParameterCount(function), arguments(),
JUMP_FUNCTION, NullCallWrapper(), call_kind);
}
@ -2652,8 +2653,9 @@ void StoreStubCompiler::GenerateStoreViaSetter(
// Call the JavaScript setter with receiver and value on the stack.
__ Push(r1, r0);
ParameterCount actual(1);
__ InvokeFunction(setter, actual, CALL_FUNCTION, NullCallWrapper(),
CALL_AS_METHOD);
ParameterCount expected(setter);
__ InvokeFunction(setter, expected, actual,
CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
} else {
// If we generate a global code snippet for deoptimization only, remember
// the place to continue after deoptimization.
@ -2837,8 +2839,9 @@ void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm,
// Call the JavaScript getter with the receiver on the stack.
__ push(r0);
ParameterCount actual(0);
__ InvokeFunction(getter, actual, CALL_FUNCTION, NullCallWrapper(),
CALL_AS_METHOD);
ParameterCount expected(getter);
__ InvokeFunction(getter, expected, actual,
CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
} else {
// If we generate a global code snippet for deoptimization only, remember
// the place to continue after deoptimization.

View File

@ -29,6 +29,8 @@
#define V8_CODE_H_
#include "allocation.h"
#include "handles.h"
#include "objects.h"
namespace v8 {
namespace internal {
@ -44,6 +46,8 @@ class ParameterCount BASE_EMBEDDED {
: reg_(reg), immediate_(0) { }
explicit ParameterCount(int immediate)
: reg_(no_reg), immediate_(immediate) { }
explicit ParameterCount(Handle<JSFunction> f)
: reg_(no_reg), immediate_(f->shared()->formal_parameter_count()) { }
bool is_reg() const { return !reg_.is(no_reg); }
bool is_immediate() const { return !is_reg(); }

View File

@ -425,6 +425,12 @@ OptimizingCompiler::Status OptimizingCompiler::GenerateAndInstallCode() {
Timer timer(this, &time_taken_to_codegen_);
ASSERT(chunk_ != NULL);
ASSERT(graph_ != NULL);
// Deferred handles reference objects that were accessible during
// graph creation. To make sure that we don't encounter inconsistencies
// between graph creation and code generation, we disallow accessing
// objects through deferred handles during the latter, with exceptions.
HandleDereferenceGuard no_deref_deferred(
isolate(), HandleDereferenceGuard::DISALLOW_DEFERRED);
Handle<Code> optimized_code = chunk_->Codegen();
if (optimized_code.is_null()) {
info()->set_bailout_reason("code generation failed");

View File

@ -476,6 +476,8 @@ Handle<ExternalArray> Factory::NewExternalArray(int length,
Handle<JSGlobalPropertyCell> Factory::NewJSGlobalPropertyCell(
Handle<Object> value) {
ALLOW_HANDLE_DEREF(isolate(),
"converting a handle into a global property cell");
CALL_HEAP_FUNCTION(
isolate(),
isolate()->heap()->AllocateJSGlobalPropertyCell(*value),

View File

@ -55,13 +55,8 @@ template <typename T>
inline bool Handle<T>::is_identical_to(const Handle<T> other) const {
ASSERT(location_ == NULL ||
reinterpret_cast<Address>(*location_) != kZapValue);
#ifdef DEBUG
if (FLAG_enable_slow_asserts) {
Isolate* isolate = Isolate::Current();
CHECK(isolate->AllowHandleDereference() ||
!isolate->optimizing_compiler_thread()->IsOptimizerThread());
}
#endif // DEBUG
// Dereferencing deferred handles to check object equality is safe.
SLOW_ASSERT(IsDereferenceAllowed(true) && other.IsDereferenceAllowed(true));
return *location_ == *other.location_;
}
@ -70,7 +65,7 @@ template <typename T>
inline T* Handle<T>::operator*() const {
ASSERT(location_ != NULL);
ASSERT(reinterpret_cast<Address>(*location_) != kHandleZapValue);
SLOW_ASSERT(Isolate::Current()->AllowHandleDereference());
SLOW_ASSERT(IsDereferenceAllowed(false));
return *BitCast<T**>(location_);
}
@ -78,10 +73,40 @@ template <typename T>
inline T** Handle<T>::location() const {
ASSERT(location_ == NULL ||
reinterpret_cast<Address>(*location_) != kZapValue);
SLOW_ASSERT(Isolate::Current()->AllowHandleDereference());
SLOW_ASSERT(IsDereferenceAllowed(false));
return location_;
}
#ifdef DEBUG
template <typename T>
bool Handle<T>::IsDereferenceAllowed(bool allow_deferred) const {
if (location_ == NULL) return true;
Object* object = *BitCast<T**>(location_);
if (object->IsSmi()) return true;
HeapObject* heap_object = HeapObject::cast(object);
Isolate* isolate = heap_object->GetIsolate();
Object** handle = reinterpret_cast<Object**>(location_);
Object** roots_array_start = isolate->heap()->roots_array_start();
if (roots_array_start <= handle &&
handle < roots_array_start + Heap::kStrongRootListLength) {
return true;
}
switch (isolate->HandleDereferenceGuardState()) {
case HandleDereferenceGuard::ALLOW:
return true;
case HandleDereferenceGuard::DISALLOW:
return false;
case HandleDereferenceGuard::DISALLOW_DEFERRED:
// Accessing maps and internalized strings is safe.
if (heap_object->IsMap()) return true;
if (heap_object->IsInternalizedString()) return true;
return allow_deferred || !isolate->IsDeferredHandle(handle);
}
return false;
}
#endif
HandleScope::HandleScope(Isolate* isolate) {
v8::ImplementationUtilities::HandleScopeData* current =
@ -181,13 +206,13 @@ inline NoHandleAllocation::~NoHandleAllocation() {
HandleDereferenceGuard::HandleDereferenceGuard(Isolate* isolate, State state)
: isolate_(isolate) {
old_state_ = isolate_->AllowHandleDereference();
isolate_->SetAllowHandleDereference(state == ALLOW);
old_state_ = isolate_->HandleDereferenceGuardState();
isolate_->SetHandleDereferenceGuardState(state);
}
HandleDereferenceGuard::~HandleDereferenceGuard() {
isolate_->SetAllowHandleDereference(old_state_);
isolate_->SetHandleDereferenceGuardState(old_state_);
}
#endif

View File

@ -73,8 +73,8 @@ class Handle {
INLINE(T** location() const);
template <class S> static Handle<T> cast(Handle<S> that) {
T::cast(*that);
return Handle<T>(reinterpret_cast<T**>(that.location()));
T::cast(*reinterpret_cast<T**>(that.location_));
return Handle<T>(reinterpret_cast<T**>(that.location_));
}
static Handle<T> null() { return Handle<T>(); }
@ -84,6 +84,10 @@ class Handle {
// implementation in api.h.
inline Handle<T> EscapeFrom(v8::HandleScope* scope);
#ifdef DEBUG
bool IsDereferenceAllowed(bool allow_deferred) const;
#endif // DEBUG
private:
T** location_;
@ -341,7 +345,7 @@ class NoHandleAllocation BASE_EMBEDDED {
class HandleDereferenceGuard BASE_EMBEDDED {
public:
enum State { ALLOW, DISALLOW };
enum State { ALLOW, DISALLOW, DISALLOW_DEFERRED };
#ifndef DEBUG
HandleDereferenceGuard(Isolate* isolate, State state) { }
~HandleDereferenceGuard() { }
@ -350,10 +354,18 @@ class HandleDereferenceGuard BASE_EMBEDDED {
inline ~HandleDereferenceGuard();
private:
Isolate* isolate_;
bool old_state_;
State old_state_;
#endif
};
#ifdef DEBUG
#define ALLOW_HANDLE_DEREF(isolate, why_this_is_safe) \
HandleDereferenceGuard allow_deref(isolate, \
HandleDereferenceGuard::ALLOW);
#else
#define ALLOW_HANDLE_DEREF(isolate, why_this_is_safe)
#endif // DEBUG
} } // namespace v8::internal
#endif // V8_HANDLES_H_

View File

@ -2200,13 +2200,6 @@ void HConstant::PrintDataTo(StringStream* stream) {
}
bool HArrayLiteral::IsCopyOnWrite() const {
if (!boilerplate_object_->IsJSObject()) return false;
return Handle<JSObject>::cast(boilerplate_object_)->elements()->map() ==
HEAP->fixed_cow_array_map();
}
void HBinaryOperation::PrintDataTo(StringStream* stream) {
left()->PrintNameTo(stream);
stream->Add(" ");

View File

@ -2226,6 +2226,8 @@ class HInvokeFunction: public HBinaryCall {
int argument_count)
: HBinaryCall(context, function, argument_count),
known_function_(known_function) {
formal_parameter_count_ = known_function.is_null()
? 0 : known_function->shared()->formal_parameter_count();
}
virtual Representation RequiredInputRepresentation(int index) {
@ -2235,20 +2237,25 @@ class HInvokeFunction: public HBinaryCall {
HValue* context() { return first(); }
HValue* function() { return second(); }
Handle<JSFunction> known_function() { return known_function_; }
int formal_parameter_count() const { return formal_parameter_count_; }
DECLARE_CONCRETE_INSTRUCTION(InvokeFunction)
private:
Handle<JSFunction> known_function_;
int formal_parameter_count_;
};
class HCallConstantFunction: public HCall<0> {
public:
HCallConstantFunction(Handle<JSFunction> function, int argument_count)
: HCall<0>(argument_count), function_(function) { }
: HCall<0>(argument_count),
function_(function),
formal_parameter_count_(function->shared()->formal_parameter_count()) {}
Handle<JSFunction> function() const { return function_; }
int formal_parameter_count() const { return formal_parameter_count_; }
bool IsApplyFunction() const {
return function_->code() ==
@ -2265,6 +2272,7 @@ class HCallConstantFunction: public HCall<0> {
private:
Handle<JSFunction> function_;
int formal_parameter_count_;
};
@ -2349,11 +2357,14 @@ class HCallGlobal: public HUnaryCall {
class HCallKnownGlobal: public HCall<0> {
public:
HCallKnownGlobal(Handle<JSFunction> target, int argument_count)
: HCall<0>(argument_count), target_(target) { }
: HCall<0>(argument_count),
target_(target),
formal_parameter_count_(target->shared()->formal_parameter_count()) { }
virtual void PrintDataTo(StringStream* stream);
Handle<JSFunction> target() const { return target_; }
int formal_parameter_count() const { return formal_parameter_count_; }
virtual Representation RequiredInputRepresentation(int index) {
return Representation::None();
@ -2363,6 +2374,7 @@ class HCallKnownGlobal: public HCall<0> {
private:
Handle<JSFunction> target_;
int formal_parameter_count_;
};
@ -3231,8 +3243,9 @@ class HConstant: public HTemplateInstruction<0> {
Handle<Object> handle() {
if (handle_.is_null()) {
handle_ = FACTORY->NewNumber(double_value_, TENURED);
handle_ = isolate()->factory()->NewNumber(double_value_, TENURED);
}
ALLOW_HANDLE_DEREF(isolate(), "smi check");
ASSERT(has_int32_value_ || !handle_->IsSmi());
return handle_;
}
@ -3256,8 +3269,6 @@ class HConstant: public HTemplateInstruction<0> {
}
ASSERT(!handle_.is_null());
HandleDereferenceGuard allow_dereference_for_immovable_check(
isolate(), HandleDereferenceGuard::ALLOW);
Heap* heap = isolate()->heap();
ASSERT(unique_id_ != UniqueValueId(heap->minus_zero_value()));
ASSERT(unique_id_ != UniqueValueId(heap->nan_value()));
@ -4882,6 +4893,12 @@ class HAllocateObject: public HTemplateInstruction<1> {
SetOperandAt(0, context);
set_representation(Representation::Tagged());
SetGVNFlag(kChangesNewSpacePromotion);
constructor_initial_map_ = constructor->has_initial_map()
? Handle<Map>(constructor->initial_map())
: Handle<Map>::null();
// If slack tracking finished, the instance size and property counts
// remain unchanged so that we can allocate memory for the object.
ASSERT(!constructor->shared()->IsInobjectSlackTrackingInProgress());
}
// Maximum instance size for which allocations will be inlined.
@ -4889,13 +4906,14 @@ class HAllocateObject: public HTemplateInstruction<1> {
HValue* context() { return OperandAt(0); }
Handle<JSFunction> constructor() { return constructor_; }
Handle<Map> constructor_initial_map() { return constructor_initial_map_; }
virtual Representation RequiredInputRepresentation(int index) {
return Representation::Tagged();
}
virtual Handle<Map> GetMonomorphicJSObjectMap() {
ASSERT(constructor()->has_initial_map());
return Handle<Map>(constructor()->initial_map());
ASSERT(!constructor_initial_map_.is_null());
return constructor_initial_map_;
}
virtual HType CalculateInferredType();
@ -4906,6 +4924,7 @@ class HAllocateObject: public HTemplateInstruction<1> {
// virtual bool IsDeletable() const { return true; }
Handle<JSFunction> constructor_;
Handle<Map> constructor_initial_map_;
};
@ -6053,27 +6072,35 @@ class HArrayLiteral: public HMaterializedLiteral<1> {
public:
HArrayLiteral(HValue* context,
Handle<HeapObject> boilerplate_object,
Handle<FixedArray> literals,
int length,
int literal_index,
int depth,
AllocationSiteMode mode)
: HMaterializedLiteral<1>(literal_index, depth, mode),
length_(length),
boilerplate_object_(boilerplate_object) {
boilerplate_object_(boilerplate_object),
literals_(literals) {
SetOperandAt(0, context);
SetGVNFlag(kChangesNewSpacePromotion);
boilerplate_elements_kind_ = boilerplate_object_->IsJSObject()
? Handle<JSObject>::cast(boilerplate_object_)->GetElementsKind()
: TERMINAL_FAST_ELEMENTS_KIND;
is_copy_on_write_ = boilerplate_object_->IsJSObject() &&
(Handle<JSObject>::cast(boilerplate_object_)->elements()->map() ==
HEAP->fixed_cow_array_map());
}
HValue* context() { return OperandAt(0); }
ElementsKind boilerplate_elements_kind() const {
if (!boilerplate_object_->IsJSObject()) {
return TERMINAL_FAST_ELEMENTS_KIND;
}
return Handle<JSObject>::cast(boilerplate_object_)->GetElementsKind();
return boilerplate_elements_kind_;
}
Handle<HeapObject> boilerplate_object() const { return boilerplate_object_; }
Handle<FixedArray> literals() const { return literals_; }
int length() const { return length_; }
bool IsCopyOnWrite() const;
bool IsCopyOnWrite() const { return is_copy_on_write_; }
virtual Representation RequiredInputRepresentation(int index) {
return Representation::Tagged();
@ -6085,6 +6112,9 @@ class HArrayLiteral: public HMaterializedLiteral<1> {
private:
int length_;
Handle<HeapObject> boilerplate_object_;
Handle<FixedArray> literals_;
ElementsKind boilerplate_elements_kind_;
bool is_copy_on_write_;
};
@ -6092,12 +6122,15 @@ class HObjectLiteral: public HMaterializedLiteral<1> {
public:
HObjectLiteral(HValue* context,
Handle<FixedArray> constant_properties,
Handle<FixedArray> literals,
bool fast_elements,
int literal_index,
int depth,
bool has_function)
: HMaterializedLiteral<1>(literal_index, depth),
constant_properties_(constant_properties),
constant_properties_length_(constant_properties->length()),
literals_(literals),
fast_elements_(fast_elements),
has_function_(has_function) {
SetOperandAt(0, context);
@ -6108,6 +6141,10 @@ class HObjectLiteral: public HMaterializedLiteral<1> {
Handle<FixedArray> constant_properties() const {
return constant_properties_;
}
int constant_properties_length() const {
return constant_properties_length_;
}
Handle<FixedArray> literals() const { return literals_; }
bool fast_elements() const { return fast_elements_; }
bool has_function() const { return has_function_; }
@ -6120,8 +6157,10 @@ class HObjectLiteral: public HMaterializedLiteral<1> {
private:
Handle<FixedArray> constant_properties_;
bool fast_elements_;
bool has_function_;
int constant_properties_length_;
Handle<FixedArray> literals_;
bool fast_elements_ : 1;
bool has_function_ : 1;
};
@ -6164,7 +6203,11 @@ class HFunctionLiteral: public HTemplateInstruction<1> {
HFunctionLiteral(HValue* context,
Handle<SharedFunctionInfo> shared,
bool pretenure)
: shared_info_(shared), pretenure_(pretenure) {
: shared_info_(shared),
pretenure_(pretenure),
has_no_literals_(shared->num_literals() == 0),
is_generator_(shared->is_generator()),
language_mode_(shared->language_mode()) {
SetOperandAt(0, context);
set_representation(Representation::Tagged());
SetGVNFlag(kChangesNewSpacePromotion);
@ -6181,12 +6224,18 @@ class HFunctionLiteral: public HTemplateInstruction<1> {
Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
bool pretenure() const { return pretenure_; }
bool has_no_literals() const { return has_no_literals_; }
bool is_generator() const { return is_generator_; }
LanguageMode language_mode() const { return language_mode_; }
private:
virtual bool IsDeletable() const { return true; }
Handle<SharedFunctionInfo> shared_info_;
bool pretenure_;
bool pretenure_ : 1;
bool has_no_literals_ : 1;
bool is_generator_ : 1;
LanguageMode language_mode_;
};

View File

@ -509,9 +509,7 @@ class ReachabilityAnalyzer BASE_EMBEDDED {
void HGraph::Verify(bool do_full_verify) const {
// Allow dereferencing for debug mode verification.
HandleDereferenceGuard allow_handle_deref(isolate(),
HandleDereferenceGuard::ALLOW);
ALLOW_HANDLE_DEREF(isolate(), "debug mode verification");
for (int i = 0; i < blocks_.length(); i++) {
HBasicBlock* block = blocks_.at(i);
@ -6348,9 +6346,11 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
pointer_size,
DONT_TRACK_ALLOCATION_SITE);
} else {
Handle<FixedArray> closure_literals(closure->literals(), isolate());
literal = AddInstruction(
new(zone()) HObjectLiteral(context,
expr->constant_properties(),
closure_literals,
expr->fast_elements(),
expr->literal_index(),
expr->depth(),
@ -6439,7 +6439,7 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
HValue* context = environment()->LookupContext();
HInstruction* literal;
Handle<FixedArray> literals(environment()->closure()->literals());
Handle<FixedArray> literals(environment()->closure()->literals(), isolate());
Handle<Object> raw_boilerplate(literals->get(expr->literal_index()),
isolate());
@ -6491,6 +6491,7 @@ void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
literal = AddInstruction(
new(zone()) HArrayLiteral(context,
original_boilerplate_object,
literals,
length,
expr->literal_index(),
expr->depth(),
@ -11456,16 +11457,14 @@ void HTracer::TraceCompilation(CompilationInfo* info) {
void HTracer::TraceLithium(const char* name, LChunk* chunk) {
ASSERT(!FLAG_parallel_recompilation);
HandleDereferenceGuard allow_handle_deref(chunk->isolate(),
HandleDereferenceGuard::ALLOW);
ALLOW_HANDLE_DEREF(chunk->isolate(), "debug output");
Trace(name, chunk->graph(), chunk);
}
void HTracer::TraceHydrogen(const char* name, HGraph* graph) {
ASSERT(!FLAG_parallel_recompilation);
HandleDereferenceGuard allow_handle_deref(graph->isolate(),
HandleDereferenceGuard::ALLOW);
ALLOW_HANDLE_DEREF(graph->isolate(), "debug output");
Trace(name, graph, NULL);
}

View File

@ -330,9 +330,14 @@ Immediate::Immediate(Label* internal_offset) {
Immediate::Immediate(Handle<Object> handle) {
#ifdef DEBUG
Isolate* isolate = Isolate::Current();
#endif
ALLOW_HANDLE_DEREF(isolate,
"using and embedding raw address, heap object check");
// Verify all Objects referred by code are NOT in new space.
Object* obj = *handle;
ASSERT(!HEAP->InNewSpace(obj));
ASSERT(!isolate->heap()->InNewSpace(obj));
if (obj->IsHeapObject()) {
x_ = reinterpret_cast<intptr_t>(handle.location());
rmode_ = RelocInfo::EMBEDDED_OBJECT;
@ -363,6 +368,7 @@ void Assembler::emit(uint32_t x) {
void Assembler::emit(Handle<Object> handle) {
ALLOW_HANDLE_DEREF(isolate(), "heap object check");
// Verify all Objects referred by code are NOT in new space.
Object* obj = *handle;
ASSERT(!isolate()->heap()->InNewSpace(obj));
@ -386,6 +392,14 @@ void Assembler::emit(uint32_t x, RelocInfo::Mode rmode, TypeFeedbackId id) {
}
void Assembler::emit(Handle<Code> code,
RelocInfo::Mode rmode,
TypeFeedbackId id) {
ALLOW_HANDLE_DEREF(isolate(), "embedding raw address");
emit(reinterpret_cast<intptr_t>(code.location()), rmode, id);
}
void Assembler::emit(const Immediate& x) {
if (x.rmode_ == RelocInfo::INTERNAL_REFERENCE) {
Label* label = reinterpret_cast<Label*>(x.x_);

View File

@ -1459,7 +1459,7 @@ void Assembler::call(Handle<Code> code,
EnsureSpace ensure_space(this);
ASSERT(RelocInfo::IsCodeTarget(rmode));
EMIT(0xE8);
emit(reinterpret_cast<intptr_t>(code.location()), rmode, ast_id);
emit(code, rmode, ast_id);
}
@ -1513,7 +1513,7 @@ void Assembler::jmp(Handle<Code> code, RelocInfo::Mode rmode) {
EnsureSpace ensure_space(this);
ASSERT(RelocInfo::IsCodeTarget(rmode));
EMIT(0xE9);
emit(reinterpret_cast<intptr_t>(code.location()), rmode);
emit(code, rmode);
}
@ -1568,7 +1568,7 @@ void Assembler::j(Condition cc, Handle<Code> code) {
// 0000 1111 1000 tttn #32-bit disp
EMIT(0x0F);
EMIT(0x80 | cc);
emit(reinterpret_cast<intptr_t>(code.location()), RelocInfo::CODE_TARGET);
emit(code, RelocInfo::CODE_TARGET);
}

View File

@ -411,6 +411,7 @@ class Operand BASE_EMBEDDED {
}
static Operand Cell(Handle<JSGlobalPropertyCell> cell) {
ALLOW_HANDLE_DEREF(Isolate::Current(), "embedding raw address");
return Operand(reinterpret_cast<int32_t>(cell.location()),
RelocInfo::GLOBAL_PROPERTY_CELL);
}
@ -1149,6 +1150,9 @@ class Assembler : public AssemblerBase {
inline void emit(uint32_t x,
RelocInfo::Mode rmode,
TypeFeedbackId id = TypeFeedbackId::None());
inline void emit(Handle<Code> code,
RelocInfo::Mode rmode,
TypeFeedbackId id = TypeFeedbackId::None());
inline void emit(const Immediate& x);
inline void emit_w(const Immediate& x);

View File

@ -635,7 +635,7 @@ void LCodeGen::WriteTranslation(LEnvironment* environment,
pushed_arguments_index,
pushed_arguments_count);
bool has_closure_id = !info()->closure().is_null() &&
*info()->closure() != *environment->closure();
!info()->closure().is_identical_to(environment->closure());
int closure_id = has_closure_id
? DefineDeoptimizationLiteral(environment->closure())
: Translation::kSelfLiteralId;
@ -1002,10 +1002,13 @@ void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
Handle<FixedArray> literals =
factory()->NewFixedArray(deoptimization_literals_.length(), TENURED);
for (int i = 0; i < deoptimization_literals_.length(); i++) {
literals->set(i, *deoptimization_literals_[i]);
{ ALLOW_HANDLE_DEREF(isolate(),
"copying a ZoneList of handles into a FixedArray");
for (int i = 0; i < deoptimization_literals_.length(); i++) {
literals->set(i, *deoptimization_literals_[i]);
}
data->SetLiteralArray(*literals);
}
data->SetLiteralArray(*literals);
data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id().ToInt()));
data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_));
@ -1787,6 +1790,7 @@ void LCodeGen::DoConstantD(LConstantD* instr) {
void LCodeGen::DoConstantT(LConstantT* instr) {
Register reg = ToRegister(instr->result());
Handle<Object> handle = instr->value();
ALLOW_HANDLE_DEREF(isolate(), "smi check");
if (handle->IsHeapObject()) {
__ LoadHeapObject(reg, Handle<HeapObject>::cast(handle));
} else {
@ -3006,6 +3010,7 @@ void LCodeGen::EmitPushTaggedOperand(LOperand* operand) {
ASSERT(!operand->IsDoubleRegister());
if (operand->IsConstantOperand()) {
Handle<Object> object = ToHandle(LConstantOperand::cast(operand));
ALLOW_HANDLE_DEREF(isolate(), "smi check");
if (object->IsSmi()) {
__ Push(Handle<Smi>::cast(object));
} else {
@ -3590,12 +3595,15 @@ void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) {
void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
int formal_parameter_count,
int arity,
LInstruction* instr,
CallKind call_kind,
EDIState edi_state) {
bool can_invoke_directly = !function->NeedsArgumentsAdaption() ||
function->shared()->formal_parameter_count() == arity;
bool dont_adapt_arguments =
formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel;
bool can_invoke_directly =
dont_adapt_arguments || formal_parameter_count == arity;
LPointerMap* pointers = instr->pointer_map();
RecordPosition(pointers->position());
@ -3610,13 +3618,13 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
// Set eax to arguments count if adaption is not needed. Assumes that eax
// is available to write to at this point.
if (!function->NeedsArgumentsAdaption()) {
if (dont_adapt_arguments) {
__ mov(eax, arity);
}
// Invoke function directly.
__ SetCallKind(ecx, call_kind);
if (*function == *info()->closure()) {
if (function.is_identical_to(info()->closure())) {
__ CallSelf();
} else {
__ call(FieldOperand(edi, JSFunction::kCodeEntryOffset));
@ -3627,14 +3635,17 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
SafepointGenerator generator(
this, pointers, Safepoint::kLazyDeopt);
ParameterCount count(arity);
__ InvokeFunction(function, count, CALL_FUNCTION, generator, call_kind);
ParameterCount expected(formal_parameter_count);
__ InvokeFunction(
function, expected, count, CALL_FUNCTION, generator, call_kind);
}
}
void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
ASSERT(ToRegister(instr->result()).is(eax));
CallKnownFunction(instr->function(),
CallKnownFunction(instr->hydrogen()->function(),
instr->hydrogen()->formal_parameter_count(),
instr->arity(),
instr,
CALL_AS_METHOD,
@ -4096,7 +4107,8 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
ASSERT(ToRegister(instr->function()).is(edi));
ASSERT(instr->HasPointerMap());
if (instr->known_function().is_null()) {
Handle<JSFunction> known_function = instr->hydrogen()->known_function();
if (known_function.is_null()) {
LPointerMap* pointers = instr->pointer_map();
RecordPosition(pointers->position());
SafepointGenerator generator(
@ -4104,7 +4116,8 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
ParameterCount count(instr->arity());
__ InvokeFunction(edi, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
} else {
CallKnownFunction(instr->known_function(),
CallKnownFunction(known_function,
instr->hydrogen()->formal_parameter_count(),
instr->arity(),
instr,
CALL_AS_METHOD,
@ -4164,7 +4177,8 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
ASSERT(ToRegister(instr->result()).is(eax));
CallKnownFunction(instr->target(),
CallKnownFunction(instr->hydrogen()->target(),
instr->hydrogen()->formal_parameter_count(),
instr->arity(),
instr,
CALL_AS_FUNCTION,
@ -5890,16 +5904,12 @@ void LCodeGen::DoAllocateObject(LAllocateObject* instr) {
Register result = ToRegister(instr->result());
Register scratch = ToRegister(instr->temp());
Handle<JSFunction> constructor = instr->hydrogen()->constructor();
Handle<Map> initial_map(constructor->initial_map());
Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map();
int instance_size = initial_map->instance_size();
ASSERT(initial_map->pre_allocated_property_fields() +
initial_map->unused_property_fields() -
initial_map->inobject_properties() == 0);
// Allocate memory for the object. The initial map might change when
// the constructor's prototype changes, but instance size and property
// counts remain unchanged (if slack tracking finished).
ASSERT(!constructor->shared()->IsInobjectSlackTrackingInProgress());
__ Allocate(instance_size, result, no_reg, scratch, deferred->entry(),
TAG_OBJECT);
@ -5950,8 +5960,7 @@ void LCodeGen::DoAllocateObject(LAllocateObject* instr) {
void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) {
Register result = ToRegister(instr->result());
Handle<JSFunction> constructor = instr->hydrogen()->constructor();
Handle<Map> initial_map(constructor->initial_map());
Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map();
int instance_size = initial_map->instance_size();
// TODO(3095996): Get rid of this. For now, we need to make the
@ -6030,7 +6039,7 @@ void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
ASSERT(ToRegister(instr->context()).is(esi));
Handle<FixedArray> literals(instr->environment()->closure()->literals());
Handle<FixedArray> literals = instr->hydrogen()->literals();
ElementsKind boilerplate_elements_kind =
instr->hydrogen()->boilerplate_elements_kind();
AllocationSiteMode allocation_site_mode =
@ -6091,7 +6100,7 @@ void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) {
ASSERT(ToRegister(instr->context()).is(esi));
Handle<FixedArray> literals(instr->environment()->closure()->literals());
Handle<FixedArray> literals = instr->hydrogen()->literals();
Handle<FixedArray> constant_properties =
instr->hydrogen()->constant_properties();
@ -6104,7 +6113,7 @@ void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) {
// Set up the parameters to the stub/runtime call and pick the right
// runtime function or stub to call.
int properties_count = constant_properties->length() / 2;
int properties_count = instr->hydrogen()->constant_properties_length() / 2;
if (instr->hydrogen()->depth() > 1) {
__ PushHeapObject(literals);
__ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index())));
@ -6192,19 +6201,17 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
ASSERT(ToRegister(instr->context()).is(esi));
// Use the fast case closure allocation code that allocates in new
// space for nested functions that don't need literals cloning.
Handle<SharedFunctionInfo> shared_info = instr->shared_info();
bool pretenure = instr->hydrogen()->pretenure();
if (!pretenure && shared_info->num_literals() == 0) {
FastNewClosureStub stub(shared_info->language_mode(),
shared_info->is_generator());
__ push(Immediate(shared_info));
if (!pretenure && instr->hydrogen()->has_no_literals()) {
FastNewClosureStub stub(instr->hydrogen()->language_mode(),
instr->hydrogen()->is_generator());
__ push(Immediate(instr->hydrogen()->shared_info()));
CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
} else {
__ push(esi);
__ push(Immediate(shared_info));
__ push(Immediate(pretenure
? factory()->true_value()
: factory()->false_value()));
__ push(Immediate(instr->hydrogen()->shared_info()));
__ push(Immediate(pretenure ? factory()->true_value()
: factory()->false_value()));
CallRuntime(Runtime::kNewClosure, 3, instr);
}
}

View File

@ -264,6 +264,7 @@ class LCodeGen BASE_EMBEDDED {
// Generate a direct call to a known function. Expects the function
// to be in edi.
void CallKnownFunction(Handle<JSFunction> function,
int formal_parameter_count,
int arity,
LInstruction* instr,
CallKind call_kind,

View File

@ -1864,7 +1864,6 @@ class LInvokeFunction: public LTemplateInstruction<1, 2, 0> {
virtual void PrintDataTo(StringStream* stream);
int arity() const { return hydrogen()->argument_count() - 1; }
Handle<JSFunction> known_function() { return hydrogen()->known_function(); }
};
@ -1947,7 +1946,6 @@ class LCallKnownGlobal: public LTemplateInstruction<1, 0, 0> {
virtual void PrintDataTo(StringStream* stream);
Handle<JSFunction> target() const { return hydrogen()->target(); }
int arity() const { return hydrogen()->argument_count() - 1; }
};
@ -2615,8 +2613,6 @@ class LFunctionLiteral: public LTemplateInstruction<1, 1, 0> {
DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function-literal")
DECLARE_HYDROGEN_ACCESSOR(FunctionLiteral)
Handle<SharedFunctionInfo> shared_info() { return hydrogen()->shared_info(); }
};

View File

@ -2278,6 +2278,7 @@ void MacroAssembler::InvokeFunction(Register fun,
void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
const ParameterCount& expected,
const ParameterCount& actual,
InvokeFlag flag,
const CallWrapper& call_wrapper,
@ -2289,7 +2290,6 @@ void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
LoadHeapObject(edi, function);
mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
ParameterCount expected(function->shared()->formal_parameter_count());
// We call indirectly through the code field in the function to
// allow recompilation to take effect without changing any of the
// call sites.
@ -2480,6 +2480,7 @@ int MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
void MacroAssembler::LoadHeapObject(Register result,
Handle<HeapObject> object) {
ALLOW_HANDLE_DEREF(isolate(), "embedding raw address");
if (isolate()->heap()->InNewSpace(*object)) {
Handle<JSGlobalPropertyCell> cell =
isolate()->factory()->NewJSGlobalPropertyCell(object);
@ -2491,6 +2492,7 @@ void MacroAssembler::LoadHeapObject(Register result,
void MacroAssembler::PushHeapObject(Handle<HeapObject> object) {
ALLOW_HANDLE_DEREF(isolate(), "using raw address");
if (isolate()->heap()->InNewSpace(*object)) {
Handle<JSGlobalPropertyCell> cell =
isolate()->factory()->NewJSGlobalPropertyCell(object);

View File

@ -271,6 +271,7 @@ class MacroAssembler: public Assembler {
void PushHeapObject(Handle<HeapObject> object);
void LoadObject(Register result, Handle<Object> object) {
ALLOW_HANDLE_DEREF(isolate(), "heap object check");
if (object->IsHeapObject()) {
LoadHeapObject(result, Handle<HeapObject>::cast(object));
} else {
@ -320,6 +321,7 @@ class MacroAssembler: public Assembler {
CallKind call_kind);
void InvokeFunction(Handle<JSFunction> function,
const ParameterCount& expected,
const ParameterCount& actual,
InvokeFlag flag,
const CallWrapper& call_wrapper,

View File

@ -635,7 +635,8 @@ class CallInterceptorCompiler BASE_EMBEDDED {
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(optimization.constant_function(), arguments_,
Handle<JSFunction> fun = optimization.constant_function();
__ InvokeFunction(fun, ParameterCount(fun), arguments_,
JUMP_FUNCTION, NullCallWrapper(), call_kind);
}
@ -2056,8 +2057,8 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(function, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
__ InvokeFunction(function, ParameterCount(function), arguments(),
JUMP_FUNCTION, NullCallWrapper(), call_kind);
__ bind(&miss);
// ecx: function name.
@ -2186,8 +2187,8 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
__ bind(&slow);
__ InvokeFunction(function, arguments(), JUMP_FUNCTION,
NullCallWrapper(), CALL_AS_METHOD);
__ InvokeFunction(function, ParameterCount(function), arguments(),
JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
__ bind(&miss);
// ecx: function name.
@ -2291,8 +2292,8 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
__ bind(&slow);
__ InvokeFunction(function, arguments(), JUMP_FUNCTION,
NullCallWrapper(), CALL_AS_METHOD);
__ InvokeFunction(function, ParameterCount(function), arguments(),
JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
__ bind(&miss);
// ecx: function name.
@ -2474,8 +2475,8 @@ void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) {
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(function, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
__ InvokeFunction(function, ParameterCount(function), arguments(),
JUMP_FUNCTION, NullCallWrapper(), call_kind);
}
@ -2687,8 +2688,9 @@ void StoreStubCompiler::GenerateStoreViaSetter(
__ push(edx);
__ push(eax);
ParameterCount actual(1);
__ InvokeFunction(setter, actual, CALL_FUNCTION, NullCallWrapper(),
CALL_AS_METHOD);
ParameterCount expected(setter);
__ InvokeFunction(setter, expected, actual,
CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
} else {
// If we generate a global code snippet for deoptimization only, remember
// the place to continue after deoptimization.
@ -2900,8 +2902,9 @@ void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm,
// Call the JavaScript getter with the receiver on the stack.
__ push(edx);
ParameterCount actual(0);
__ InvokeFunction(getter, actual, CALL_FUNCTION, NullCallWrapper(),
CALL_AS_METHOD);
ParameterCount expected(getter);
__ InvokeFunction(getter, expected, actual,
CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
} else {
// If we generate a global code snippet for deoptimization only, remember
// the place to continue after deoptimization.

View File

@ -507,6 +507,29 @@ void Isolate::IterateDeferredHandles(ObjectVisitor* visitor) {
}
#ifdef DEBUG
bool Isolate::IsDeferredHandle(Object** handle) {
// Each DeferredHandles instance keeps the handles to one job in the
// parallel recompilation queue, containing a list of blocks. Each block
// contains kHandleBlockSize handles except for the first block, which may
// not be fully filled.
// We iterate through all the blocks to see whether the argument handle
// belongs to one of the blocks. If so, it is deferred.
for (DeferredHandles* deferred = deferred_handles_head_;
deferred != NULL;
deferred = deferred->next_) {
List<Object**>* blocks = &deferred->blocks_;
for (int i = 0; i < blocks->length(); i++) {
Object** block_limit = (i == 0) ? deferred->first_block_limit_
: blocks->at(i) + kHandleBlockSize;
if (blocks->at(i) <= handle && handle < block_limit) return true;
}
}
return false;
}
#endif // DEBUG
void Isolate::RegisterTryCatchHandler(v8::TryCatch* that) {
// The ARM simulator has a separate JS stack. We therefore register
// the C++ try catch handler with the simulator and get back an
@ -1757,8 +1780,8 @@ Isolate::Isolate()
memset(code_kind_statistics_, 0,
sizeof(code_kind_statistics_[0]) * Code::NUMBER_OF_KINDS);
allow_compiler_thread_handle_deref_ = true;
allow_execution_thread_handle_deref_ = true;
compiler_thread_handle_deref_state_ = HandleDereferenceGuard::ALLOW;
execution_thread_handle_deref_state_ = HandleDereferenceGuard::ALLOW;
#endif
#ifdef ENABLE_DEBUGGER_SUPPORT
@ -2379,27 +2402,28 @@ void Isolate::UnlinkDeferredHandles(DeferredHandles* deferred) {
#ifdef DEBUG
bool Isolate::AllowHandleDereference() {
if (allow_execution_thread_handle_deref_ &&
allow_compiler_thread_handle_deref_) {
HandleDereferenceGuard::State Isolate::HandleDereferenceGuardState() {
if (execution_thread_handle_deref_state_ == HandleDereferenceGuard::ALLOW &&
compiler_thread_handle_deref_state_ == HandleDereferenceGuard::ALLOW) {
// Short-cut to avoid polling thread id.
return true;
return HandleDereferenceGuard::ALLOW;
}
if (FLAG_parallel_recompilation &&
optimizing_compiler_thread()->IsOptimizerThread()) {
return allow_compiler_thread_handle_deref_;
return compiler_thread_handle_deref_state_;
} else {
return allow_execution_thread_handle_deref_;
return execution_thread_handle_deref_state_;
}
}
void Isolate::SetAllowHandleDereference(bool allow) {
void Isolate::SetHandleDereferenceGuardState(
HandleDereferenceGuard::State state) {
if (FLAG_parallel_recompilation &&
optimizing_compiler_thread()->IsOptimizerThread()) {
allow_compiler_thread_handle_deref_ = allow;
compiler_thread_handle_deref_state_ = state;
} else {
allow_execution_thread_handle_deref_ = allow;
execution_thread_handle_deref_state_ = state;
}
}
#endif

View File

@ -991,9 +991,9 @@ class Isolate {
int* code_kind_statistics() { return code_kind_statistics_; }
bool AllowHandleDereference();
HandleDereferenceGuard::State HandleDereferenceGuardState();
void SetAllowHandleDereference(bool allow);
void SetHandleDereferenceGuardState(HandleDereferenceGuard::State state);
#endif
#if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
@ -1074,6 +1074,10 @@ class Isolate {
void LinkDeferredHandles(DeferredHandles* deferred_handles);
void UnlinkDeferredHandles(DeferredHandles* deferred_handles);
#ifdef DEBUG
bool IsDeferredHandle(Object** location);
#endif // DEBUG
OptimizingCompilerThread* optimizing_compiler_thread() {
return &optimizing_compiler_thread_;
}
@ -1292,8 +1296,8 @@ class Isolate {
JSObject::SpillInformation js_spill_information_;
int code_kind_statistics_[Code::NUMBER_OF_KINDS];
bool allow_compiler_thread_handle_deref_;
bool allow_execution_thread_handle_deref_;
HandleDereferenceGuard::State compiler_thread_handle_deref_state_;
HandleDereferenceGuard::State execution_thread_handle_deref_state_;
#endif
#ifdef ENABLE_DEBUGGER_SUPPORT

View File

@ -9055,6 +9055,7 @@ void Code::CopyFrom(const CodeDesc& desc) {
RelocInfo::kApplyMask;
// Needed to find target_object and runtime_entry on X64
Assembler* origin = desc.origin;
ALLOW_HANDLE_DEREF(GetIsolate(), "embedding raw addresses into code");
for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
RelocInfo::Mode mode = it.rinfo()->rmode();
if (mode == RelocInfo::EMBEDDED_OBJECT) {

View File

@ -1590,6 +1590,7 @@ void Assembler::movl(const Operand& dst, Label* src) {
void Assembler::movq(Register dst, Handle<Object> value, RelocInfo::Mode mode) {
ALLOW_HANDLE_DEREF(isolate(), "using and embedding raw address");
// If there is no relocation info, emit the value of the handle efficiently
// (possibly using less that 8 bytes for the value).
if (RelocInfo::IsNone(mode)) {

View File

@ -483,7 +483,7 @@ void LCodeGen::WriteTranslation(LEnvironment* environment,
pushed_arguments_index,
pushed_arguments_count);
bool has_closure_id = !info()->closure().is_null() &&
*info()->closure() != *environment->closure();
!info()->closure().is_identical_to(environment->closure());
int closure_id = has_closure_id
? DefineDeoptimizationLiteral(environment->closure())
: Translation::kSelfLiteralId;
@ -800,10 +800,13 @@ void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
Handle<FixedArray> literals =
factory()->NewFixedArray(deoptimization_literals_.length(), TENURED);
for (int i = 0; i < deoptimization_literals_.length(); i++) {
literals->set(i, *deoptimization_literals_[i]);
{ ALLOW_HANDLE_DEREF(isolate(),
"copying a ZoneList of handles into a FixedArray");
for (int i = 0; i < deoptimization_literals_.length(); i++) {
literals->set(i, *deoptimization_literals_[i]);
}
data->SetLiteralArray(*literals);
}
data->SetLiteralArray(*literals);
data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id().ToInt()));
data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_));
@ -1557,6 +1560,7 @@ void LCodeGen::DoConstantD(LConstantD* instr) {
void LCodeGen::DoConstantT(LConstantT* instr) {
Handle<Object> value = instr->value();
ALLOW_HANDLE_DEREF(isolate(), "smi check");
if (value->IsSmi()) {
__ Move(ToRegister(instr->result()), value);
} else {
@ -3313,12 +3317,15 @@ void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) {
void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
int formal_parameter_count,
int arity,
LInstruction* instr,
CallKind call_kind,
RDIState rdi_state) {
bool can_invoke_directly = !function->NeedsArgumentsAdaption() ||
function->shared()->formal_parameter_count() == arity;
bool dont_adapt_arguments =
formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel;
bool can_invoke_directly =
dont_adapt_arguments || formal_parameter_count == arity;
LPointerMap* pointers = instr->pointer_map();
RecordPosition(pointers->position());
@ -3333,13 +3340,13 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
// Set rax to arguments count if adaption is not needed. Assumes that rax
// is available to write to at this point.
if (!function->NeedsArgumentsAdaption()) {
if (dont_adapt_arguments) {
__ Set(rax, arity);
}
// Invoke function.
__ SetCallKind(rcx, call_kind);
if (*function == *info()->closure()) {
if (function.is_identical_to(info()->closure())) {
__ CallSelf();
} else {
__ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset));
@ -3352,7 +3359,9 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
SafepointGenerator generator(
this, pointers, Safepoint::kLazyDeopt);
ParameterCount count(arity);
__ InvokeFunction(function, count, CALL_FUNCTION, generator, call_kind);
ParameterCount expected(formal_parameter_count);
__ InvokeFunction(
function, expected, count, CALL_FUNCTION, generator, call_kind);
}
// Restore context.
@ -3362,7 +3371,8 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
ASSERT(ToRegister(instr->result()).is(rax));
CallKnownFunction(instr->function(),
CallKnownFunction(instr->hydrogen()->function(),
instr->hydrogen()->formal_parameter_count(),
instr->arity(),
instr,
CALL_AS_METHOD,
@ -3802,7 +3812,8 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
ASSERT(ToRegister(instr->function()).is(rdi));
ASSERT(instr->HasPointerMap());
if (instr->known_function().is_null()) {
Handle<JSFunction> known_function = instr->hydrogen()->known_function();
if (known_function.is_null()) {
LPointerMap* pointers = instr->pointer_map();
RecordPosition(pointers->position());
SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
@ -3810,7 +3821,8 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
__ InvokeFunction(rdi, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
} else {
CallKnownFunction(instr->known_function(),
CallKnownFunction(known_function,
instr->hydrogen()->formal_parameter_count(),
instr->arity(),
instr,
CALL_AS_METHOD,
@ -3869,7 +3881,8 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
ASSERT(ToRegister(instr->result()).is(rax));
CallKnownFunction(instr->target(),
CallKnownFunction(instr->hydrogen()->target(),
instr->hydrogen()->formal_parameter_count(),
instr->arity(),
instr,
CALL_AS_FUNCTION,
@ -4870,6 +4883,7 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
Register reg = ToRegister(instr->value());
Handle<JSFunction> target = instr->hydrogen()->target();
ALLOW_HANDLE_DEREF(isolate(), "using raw address");
if (isolate()->heap()->InNewSpace(*target)) {
Handle<JSGlobalPropertyCell> cell =
isolate()->factory()->NewJSGlobalPropertyCell(target);
@ -4998,16 +5012,12 @@ void LCodeGen::DoAllocateObject(LAllocateObject* instr) {
Register result = ToRegister(instr->result());
Register scratch = ToRegister(instr->temp());
Handle<JSFunction> constructor = instr->hydrogen()->constructor();
Handle<Map> initial_map(constructor->initial_map());
Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map();
int instance_size = initial_map->instance_size();
ASSERT(initial_map->pre_allocated_property_fields() +
initial_map->unused_property_fields() -
initial_map->inobject_properties() == 0);
// Allocate memory for the object. The initial map might change when
// the constructor's prototype changes, but instance size and property
// counts remain unchanged (if slack tracking finished).
ASSERT(!constructor->shared()->IsInobjectSlackTrackingInProgress());
__ Allocate(instance_size, result, no_reg, scratch, deferred->entry(),
TAG_OBJECT);
@ -5058,8 +5068,7 @@ void LCodeGen::DoAllocateObject(LAllocateObject* instr) {
void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) {
Register result = ToRegister(instr->result());
Handle<JSFunction> constructor = instr->hydrogen()->constructor();
Handle<Map> initial_map(constructor->initial_map());
Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map();
int instance_size = initial_map->instance_size();
// TODO(3095996): Get rid of this. For now, we need to make the
@ -5135,7 +5144,7 @@ void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
Handle<FixedArray> literals(instr->environment()->closure()->literals());
Handle<FixedArray> literals = instr->hydrogen()->literals();
ElementsKind boilerplate_elements_kind =
instr->hydrogen()->boilerplate_elements_kind();
AllocationSiteMode allocation_site_mode =
@ -5195,7 +5204,7 @@ void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) {
Handle<FixedArray> literals(instr->environment()->closure()->literals());
Handle<FixedArray> literals = instr->hydrogen()->literals();
Handle<FixedArray> constant_properties =
instr->hydrogen()->constant_properties();
@ -5208,7 +5217,7 @@ void LCodeGen::DoObjectLiteral(LObjectLiteral* instr) {
// Set up the parameters to the stub/runtime call and pick the right
// runtime function or stub to call.
int properties_count = constant_properties->length() / 2;
int properties_count = instr->hydrogen()->constant_properties_length() / 2;
if (instr->hydrogen()->depth() > 1) {
__ PushHeapObject(literals);
__ Push(Smi::FromInt(instr->hydrogen()->literal_index()));
@ -5293,19 +5302,17 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {
void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
// Use the fast case closure allocation code that allocates in new
// space for nested functions that don't need literals cloning.
Handle<SharedFunctionInfo> shared_info = instr->shared_info();
bool pretenure = instr->hydrogen()->pretenure();
if (!pretenure && shared_info->num_literals() == 0) {
FastNewClosureStub stub(shared_info->language_mode(),
shared_info->is_generator());
__ Push(shared_info);
if (!pretenure && instr->hydrogen()->has_no_literals()) {
FastNewClosureStub stub(instr->hydrogen()->language_mode(),
instr->hydrogen()->is_generator());
__ Push(instr->hydrogen()->shared_info());
CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
} else {
__ push(rsi);
__ Push(shared_info);
__ PushRoot(pretenure ?
Heap::kTrueValueRootIndex :
Heap::kFalseValueRootIndex);
__ Push(instr->hydrogen()->shared_info());
__ PushRoot(pretenure ? Heap::kTrueValueRootIndex :
Heap::kFalseValueRootIndex);
CallRuntime(Runtime::kNewClosure, 3, instr);
}
}
@ -5322,6 +5329,7 @@ void LCodeGen::EmitPushTaggedOperand(LOperand* operand) {
ASSERT(!operand->IsDoubleRegister());
if (operand->IsConstantOperand()) {
Handle<Object> object = ToHandle(LConstantOperand::cast(operand));
ALLOW_HANDLE_DEREF(isolate(), "smi check");
if (object->IsSmi()) {
__ Push(Handle<Smi>::cast(object));
} else {

View File

@ -234,6 +234,7 @@ class LCodeGen BASE_EMBEDDED {
// Generate a direct call to a known function. Expects the function
// to be in rdi.
void CallKnownFunction(Handle<JSFunction> function,
int formal_parameter_count,
int arity,
LInstruction* instr,
CallKind call_kind,

View File

@ -1785,7 +1785,6 @@ class LInvokeFunction: public LTemplateInstruction<1, 1, 0> {
virtual void PrintDataTo(StringStream* stream);
int arity() const { return hydrogen()->argument_count() - 1; }
Handle<JSFunction> known_function() { return hydrogen()->known_function(); }
};
@ -1851,7 +1850,6 @@ class LCallKnownGlobal: public LTemplateInstruction<1, 0, 0> {
virtual void PrintDataTo(StringStream* stream);
Handle<JSFunction> target() const { return hydrogen()->target(); }
int arity() const { return hydrogen()->argument_count() - 1; }
};
@ -2403,8 +2401,6 @@ class LFunctionLiteral: public LTemplateInstruction<1, 0, 0> {
public:
DECLARE_CONCRETE_INSTRUCTION(FunctionLiteral, "function-literal")
DECLARE_HYDROGEN_ACCESSOR(FunctionLiteral)
Handle<SharedFunctionInfo> shared_info() { return hydrogen()->shared_info(); }
};

View File

@ -2286,7 +2286,7 @@ void MacroAssembler::Move(Register dst, Register src) {
void MacroAssembler::Move(Register dst, Handle<Object> source) {
ASSERT(!source->IsFailure());
ALLOW_HANDLE_DEREF(isolate(), "smi check");
if (source->IsSmi()) {
Move(dst, Smi::cast(*source));
} else {
@ -2296,7 +2296,7 @@ void MacroAssembler::Move(Register dst, Handle<Object> source) {
void MacroAssembler::Move(const Operand& dst, Handle<Object> source) {
ASSERT(!source->IsFailure());
ALLOW_HANDLE_DEREF(isolate(), "smi check");
if (source->IsSmi()) {
Move(dst, Smi::cast(*source));
} else {
@ -2307,6 +2307,7 @@ void MacroAssembler::Move(const Operand& dst, Handle<Object> source) {
void MacroAssembler::Cmp(Register dst, Handle<Object> source) {
ALLOW_HANDLE_DEREF(isolate(), "smi check");
if (source->IsSmi()) {
Cmp(dst, Smi::cast(*source));
} else {
@ -2317,6 +2318,7 @@ void MacroAssembler::Cmp(Register dst, Handle<Object> source) {
void MacroAssembler::Cmp(const Operand& dst, Handle<Object> source) {
ALLOW_HANDLE_DEREF(isolate(), "smi check");
if (source->IsSmi()) {
Cmp(dst, Smi::cast(*source));
} else {
@ -2328,6 +2330,7 @@ void MacroAssembler::Cmp(const Operand& dst, Handle<Object> source) {
void MacroAssembler::Push(Handle<Object> source) {
ALLOW_HANDLE_DEREF(isolate(), "smi check");
if (source->IsSmi()) {
Push(Smi::cast(*source));
} else {
@ -2340,6 +2343,7 @@ void MacroAssembler::Push(Handle<Object> source) {
void MacroAssembler::LoadHeapObject(Register result,
Handle<HeapObject> object) {
ALLOW_HANDLE_DEREF(isolate(), "using raw address");
if (isolate()->heap()->InNewSpace(*object)) {
Handle<JSGlobalPropertyCell> cell =
isolate()->factory()->NewJSGlobalPropertyCell(object);
@ -2352,6 +2356,7 @@ void MacroAssembler::LoadHeapObject(Register result,
void MacroAssembler::PushHeapObject(Handle<HeapObject> object) {
ALLOW_HANDLE_DEREF(isolate(), "using raw address");
if (isolate()->heap()->InNewSpace(*object)) {
Handle<JSGlobalPropertyCell> cell =
isolate()->factory()->NewJSGlobalPropertyCell(object);
@ -2367,6 +2372,7 @@ void MacroAssembler::PushHeapObject(Handle<HeapObject> object) {
void MacroAssembler::LoadGlobalCell(Register dst,
Handle<JSGlobalPropertyCell> cell) {
if (dst.is(rax)) {
ALLOW_HANDLE_DEREF(isolate(), "embedding raw address");
load_rax(cell.location(), RelocInfo::GLOBAL_PROPERTY_CELL);
} else {
movq(dst, cell, RelocInfo::GLOBAL_PROPERTY_CELL);
@ -3280,6 +3286,7 @@ void MacroAssembler::InvokeFunction(Register function,
void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
const ParameterCount& expected,
const ParameterCount& actual,
InvokeFlag flag,
const CallWrapper& call_wrapper,
@ -3295,7 +3302,6 @@ void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
// allow recompilation to take effect without changing any of the
// call sites.
movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
ParameterCount expected(function->shared()->formal_parameter_count());
InvokeCode(rdx, expected, actual, flag, call_wrapper, call_kind);
}

View File

@ -349,6 +349,7 @@ class MacroAssembler: public Assembler {
CallKind call_kind);
void InvokeFunction(Handle<JSFunction> function,
const ParameterCount& expected,
const ParameterCount& actual,
InvokeFlag flag,
const CallWrapper& call_wrapper,
@ -786,6 +787,7 @@ class MacroAssembler: public Assembler {
void PushHeapObject(Handle<HeapObject> object);
void LoadObject(Register result, Handle<Object> object) {
ALLOW_HANDLE_DEREF(isolate(), "heap object check");
if (object->IsHeapObject()) {
LoadHeapObject(result, Handle<HeapObject>::cast(object));
} else {

View File

@ -621,7 +621,8 @@ class CallInterceptorCompiler BASE_EMBEDDED {
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(optimization.constant_function(), arguments_,
Handle<JSFunction> fun = optimization.constant_function();
__ InvokeFunction(fun, ParameterCount(fun), arguments_,
JUMP_FUNCTION, NullCallWrapper(), call_kind);
}
@ -1991,8 +1992,8 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(function, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
__ InvokeFunction(function, ParameterCount(function), arguments(),
JUMP_FUNCTION, NullCallWrapper(), call_kind);
__ bind(&miss);
// rcx: function name.
@ -2106,8 +2107,8 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(function, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
__ InvokeFunction(function, ParameterCount(function), arguments(),
JUMP_FUNCTION, NullCallWrapper(), call_kind);
__ bind(&miss);
// rcx: function name.
@ -2290,8 +2291,8 @@ void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) {
CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(function, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
__ InvokeFunction(function, ParameterCount(function), arguments(),
JUMP_FUNCTION, NullCallWrapper(), call_kind);
}
@ -2503,8 +2504,9 @@ void StoreStubCompiler::GenerateStoreViaSetter(
__ push(rdx);
__ push(rax);
ParameterCount actual(1);
__ InvokeFunction(setter, actual, CALL_FUNCTION, NullCallWrapper(),
CALL_AS_METHOD);
ParameterCount expected(setter);
__ InvokeFunction(setter, expected, actual,
CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
} else {
// If we generate a global code snippet for deoptimization only, remember
// the place to continue after deoptimization.
@ -2723,8 +2725,9 @@ void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm,
// Call the JavaScript getter with the receiver on the stack.
__ push(rax);
ParameterCount actual(0);
__ InvokeFunction(getter, actual, CALL_FUNCTION, NullCallWrapper(),
CALL_AS_METHOD);
ParameterCount expected(getter);
__ InvokeFunction(getter, expected, actual,
CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
} else {
// If we generate a global code snippet for deoptimization only, remember
// the place to continue after deoptimization.