blob: 749f2fa963357703c1512b744cb7e982faefa7a5 [file] [log] [blame]
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/ic/handler-compiler.h"
#include "src/assembler-inl.h"
#include "src/field-type.h"
#include "src/ic/call-optimization.h"
#include "src/ic/handler-configuration-inl.h"
#include "src/ic/ic-inl.h"
#include "src/ic/ic.h"
#include "src/isolate-inl.h"
namespace v8 {
namespace internal {
Handle<Code> PropertyHandlerCompiler::GetCode(Handle<Name> name) {
// Create code object in the heap.
CodeDesc desc;
masm()->GetCode(isolate(), &desc);
Handle<Code> code =
factory()->NewCode(desc, Code::STUB, masm()->CodeObject());
DCHECK(code->is_stub());
code->set_stub_key(CodeStub::NoCacheKey());
#ifdef ENABLE_DISASSEMBLER
if (FLAG_print_code_stubs) {
char* raw_name = !name.is_null() && name->IsString()
? String::cast(*name)->ToCString().get()
: nullptr;
CodeTracer::Scope trace_scope(isolate()->GetCodeTracer());
OFStream os(trace_scope.file());
code->Disassemble(raw_name, os);
}
#endif
PROFILE(isolate(), CodeCreateEvent(CodeEventListener::HANDLER_TAG,
AbstractCode::cast(*code), *name));
#ifdef DEBUG
code->VerifyEmbeddedObjects();
#endif
return code;
}
#define __ ACCESS_MASM(masm())
Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg,
Handle<Name> name,
Label* miss) {
if (map()->IsPrimitiveMap() || map()->IsJSGlobalProxyMap()) {
// If the receiver is a global proxy and if we get to this point then
// the compile-time (current) native context has access to global proxy's
// native context. Since access rights revocation is not supported at all,
// we can generate a check that an execution-time native context is either
// the same as compile-time native context or has the same access token.
Handle<Context> native_context = isolate()->native_context();
Handle<WeakCell> weak_cell(native_context->self_weak_cell(), isolate());
bool compare_native_contexts_only = map()->IsPrimitiveMap();
GenerateAccessCheck(weak_cell, scratch1(), scratch2(), miss,
compare_native_contexts_only);
}
// Check that the maps starting from the prototype haven't changed.
return CheckPrototypes(object_reg, scratch1(), scratch2(), scratch3(), name,
miss);
}
// Frontend for store uses the name register. It has to be restored before a
// miss.
Register NamedStoreHandlerCompiler::FrontendHeader(Register object_reg,
Handle<Name> name,
Label* miss) {
if (map()->IsJSGlobalProxyMap()) {
Handle<Context> native_context = isolate()->native_context();
Handle<WeakCell> weak_cell(native_context->self_weak_cell(), isolate());
GenerateAccessCheck(weak_cell, scratch1(), scratch2(), miss, false);
}
return CheckPrototypes(object_reg, this->name(), scratch1(), scratch2(), name,
miss);
}
// The ICs that don't pass slot and vector through the stack have to
// save/restore them in the dispatcher.
bool PropertyHandlerCompiler::ShouldPushPopSlotAndVector() {
switch (type()) {
case LOAD:
return true;
case STORE:
return !StoreWithVectorDescriptor::kPassLastArgsOnStack;
}
UNREACHABLE();
return false;
}
Register PropertyHandlerCompiler::Frontend(Handle<Name> name) {
Label miss;
if (ShouldPushPopSlotAndVector()) PushVectorAndSlot();
Register reg = FrontendHeader(receiver(), name, &miss);
FrontendFooter(name, &miss);
// The footer consumes the vector and slot from the stack if miss occurs.
if (ShouldPushPopSlotAndVector()) DiscardVectorAndSlot();
return reg;
}
Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback(
Handle<Name> name, const CallOptimization& call_optimization,
int accessor_index, Handle<Code> slow_stub) {
DCHECK(call_optimization.is_simple_api_call());
if (V8_UNLIKELY(FLAG_runtime_stats)) {
GenerateTailCall(masm(), slow_stub);
}
Register holder = Frontend(name);
GenerateApiAccessorCall(masm(), call_optimization, map(), receiver(),
scratch2(), false, no_reg, holder, accessor_index);
return GetCode(name);
}
Handle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter(
Handle<JSObject> object, Handle<Name> name, int accessor_index,
int expected_arguments) {
Register holder = Frontend(name);
GenerateStoreViaSetter(masm(), map(), receiver(), holder, accessor_index,
expected_arguments, scratch2());
return GetCode(name);
}
Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
Handle<JSObject> object, Handle<Name> name,
const CallOptimization& call_optimization, int accessor_index,
Handle<Code> slow_stub) {
if (V8_UNLIKELY(FLAG_runtime_stats)) {
GenerateTailCall(masm(), slow_stub);
}
Register holder = Frontend(name);
if (Descriptor::kPassLastArgsOnStack) {
__ LoadParameterFromStack<Descriptor>(value(), Descriptor::kValue);
}
GenerateApiAccessorCall(masm(), call_optimization, handle(object->map()),
receiver(), scratch2(), true, value(), holder,
accessor_index);
return GetCode(name);
}
#undef __
} // namespace internal
} // namespace v8