handler-compiler.cc 5.44 KB
Newer Older
1 2 3 4
// 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.

5
#include "src/ic/handler-compiler.h"
6

7
#include "src/assembler-inl.h"
8
#include "src/field-type.h"
9
#include "src/ic/call-optimization.h"
10
#include "src/ic/handler-configuration-inl.h"
11
#include "src/ic/ic-inl.h"
12
#include "src/ic/ic.h"
13
#include "src/isolate-inl.h"
14 15 16 17

namespace v8 {
namespace internal {

18
Handle<Code> PropertyHandlerCompiler::GetCode(Handle<Name> name) {
19 20
  // Create code object in the heap.
  CodeDesc desc;
21
  masm()->GetCode(isolate(), &desc);
22 23
  Handle<Code> code =
      factory()->NewCode(desc, Code::STUB, masm()->CodeObject());
24 25
  DCHECK(code->is_stub());
  code->set_stub_key(CodeStub::NoCacheKey());
26 27 28 29 30 31 32 33 34 35 36
#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

37
  PROFILE(isolate(), CodeCreateEvent(CodeEventListener::HANDLER_TAG,
38
                                     AbstractCode::cast(*code), *name));
39

40 41 42
#ifdef DEBUG
  code->VerifyEmbeddedObjects();
#endif
43 44 45 46 47 48 49 50
  return code;
}


#define __ ACCESS_MASM(masm())

Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg,
                                                  Handle<Name> name,
51
                                                  Label* miss) {
52 53 54 55 56 57 58 59 60 61 62 63 64 65
  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);
  }

66 67
  // Check that the maps starting from the prototype haven't changed.
  return CheckPrototypes(object_reg, scratch1(), scratch2(), scratch3(), name,
68
                         miss);
69 70 71 72 73 74 75
}


// Frontend for store uses the name register. It has to be restored before a
// miss.
Register NamedStoreHandlerCompiler::FrontendHeader(Register object_reg,
                                                   Handle<Name> name,
76
                                                   Label* miss) {
77 78 79 80 81 82
  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);
  }

83
  return CheckPrototypes(object_reg, this->name(), scratch1(), scratch2(), name,
84
                         miss);
85 86
}

87 88 89 90 91 92 93 94 95 96 97 98
// 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;
}
99

100
Register PropertyHandlerCompiler::Frontend(Handle<Name> name) {
101
  Label miss;
102
  if (ShouldPushPopSlotAndVector()) PushVectorAndSlot();
103
  Register reg = FrontendHeader(receiver(), name, &miss);
104
  FrontendFooter(name, &miss);
105
  // The footer consumes the vector and slot from the stack if miss occurs.
106
  if (ShouldPushPopSlotAndVector()) DiscardVectorAndSlot();
107 108 109 110
  return reg;
}

Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback(
111
    Handle<Name> name, const CallOptimization& call_optimization,
112
    int accessor_index, Handle<Code> slow_stub) {
113
  DCHECK(call_optimization.is_simple_api_call());
114
  if (V8_UNLIKELY(FLAG_runtime_stats)) {
115
    GenerateTailCall(masm(), slow_stub);
116
  }
117 118 119
  Register holder = Frontend(name);
  GenerateApiAccessorCall(masm(), call_optimization, map(), receiver(),
                          scratch2(), false, no_reg, holder, accessor_index);
120
  return GetCode(name);
121 122 123
}

Handle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter(
124 125 126
    Handle<JSObject> object, Handle<Name> name, int accessor_index,
    int expected_arguments) {
  Register holder = Frontend(name);
127
  GenerateStoreViaSetter(masm(), map(), receiver(), holder, accessor_index,
128
                         expected_arguments, scratch2());
129

130
  return GetCode(name);
131 132 133 134
}

Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
    Handle<JSObject> object, Handle<Name> name,
135 136
    const CallOptimization& call_optimization, int accessor_index,
    Handle<Code> slow_stub) {
137
  if (V8_UNLIKELY(FLAG_runtime_stats)) {
138
    GenerateTailCall(masm(), slow_stub);
139
  }
140
  Register holder = Frontend(name);
141 142 143
  if (Descriptor::kPassLastArgsOnStack) {
    __ LoadParameterFromStack<Descriptor>(value(), Descriptor::kValue);
  }
144 145 146
  GenerateApiAccessorCall(masm(), call_optimization, handle(object->map()),
                          receiver(), scratch2(), true, value(), holder,
                          accessor_index);
147
  return GetCode(name);
148 149 150 151 152
}


#undef __

153 154
}  // namespace internal
}  // namespace v8