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:
parent
d352df8131
commit
28bbe46a98
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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(); }
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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(); }
|
||||
|
@ -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");
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
|
@ -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_
|
||||
|
@ -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(" ");
|
||||
|
@ -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_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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_);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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(); }
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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)) {
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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(); }
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user