// 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
