// 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/call-optimization.h"
#include "src/objects-inl.h"

namespace v8 {
namespace internal {

CallOptimization::CallOptimization(Isolate* isolate, Handle<Object> function) {
  constant_function_ = Handle<JSFunction>::null();
  is_simple_api_call_ = false;
  expected_receiver_type_ = Handle<FunctionTemplateInfo>::null();
  api_call_info_ = Handle<CallHandlerInfo>::null();
  if (function->IsJSFunction()) {
    Initialize(isolate, Handle<JSFunction>::cast(function));
  } else if (function->IsFunctionTemplateInfo()) {
    Initialize(isolate, Handle<FunctionTemplateInfo>::cast(function));
  }
}

Context CallOptimization::GetAccessorContext(Map holder_map) const {
  if (is_constant_call()) {
    return constant_function_->context()->native_context();
  }
  JSFunction constructor = JSFunction::cast(holder_map->GetConstructor());
  return constructor->context()->native_context();
}

bool CallOptimization::IsCrossContextLazyAccessorPair(Context native_context,
                                                      Map holder_map) const {
  DCHECK(native_context->IsNativeContext());
  if (is_constant_call()) return false;
  return native_context != GetAccessorContext(holder_map);
}

Handle<JSObject> CallOptimization::LookupHolderOfExpectedType(
    Handle<Map> object_map, HolderLookup* holder_lookup) const {
  DCHECK(is_simple_api_call());
  if (!object_map->IsJSObjectMap()) {
    *holder_lookup = kHolderNotFound;
    return Handle<JSObject>::null();
  }
  if (expected_receiver_type_.is_null() ||
      expected_receiver_type_->IsTemplateFor(*object_map)) {
    *holder_lookup = kHolderIsReceiver;
    return Handle<JSObject>::null();
  }
  if (object_map->has_hidden_prototype()) {
    JSObject raw_prototype = JSObject::cast(object_map->prototype());
    Handle<JSObject> prototype(raw_prototype, raw_prototype->GetIsolate());
    object_map = handle(prototype->map(), prototype->GetIsolate());
    if (expected_receiver_type_->IsTemplateFor(*object_map)) {
      *holder_lookup = kHolderFound;
      return prototype;
    }
  }
  *holder_lookup = kHolderNotFound;
  return Handle<JSObject>::null();
}


bool CallOptimization::IsCompatibleReceiver(Handle<Object> receiver,
                                            Handle<JSObject> holder) const {
  DCHECK(is_simple_api_call());
  if (!receiver->IsHeapObject()) return false;
  Handle<Map> map(HeapObject::cast(*receiver)->map(), holder->GetIsolate());
  return IsCompatibleReceiverMap(map, holder);
}


bool CallOptimization::IsCompatibleReceiverMap(Handle<Map> map,
                                               Handle<JSObject> holder) const {
  HolderLookup holder_lookup;
  Handle<JSObject> api_holder = LookupHolderOfExpectedType(map, &holder_lookup);
  switch (holder_lookup) {
    case kHolderNotFound:
      return false;
    case kHolderIsReceiver:
      return true;
    case kHolderFound:
      if (api_holder.is_identical_to(holder)) return true;
      // Check if holder is in prototype chain of api_holder.
      {
        JSObject object = *api_holder;
        while (true) {
          Object prototype = object->map()->prototype();
          if (!prototype->IsJSObject()) return false;
          if (prototype == *holder) return true;
          object = JSObject::cast(prototype);
        }
      }
      break;
  }
  UNREACHABLE();
}

void CallOptimization::Initialize(
    Isolate* isolate, Handle<FunctionTemplateInfo> function_template_info) {
  if (function_template_info->call_code()->IsUndefined(isolate)) return;
  api_call_info_ = handle(
      CallHandlerInfo::cast(function_template_info->call_code()), isolate);

  if (!function_template_info->signature()->IsUndefined(isolate)) {
    expected_receiver_type_ =
        handle(FunctionTemplateInfo::cast(function_template_info->signature()),
               isolate);
  }
  is_simple_api_call_ = true;
}

void CallOptimization::Initialize(Isolate* isolate,
                                  Handle<JSFunction> function) {
  if (function.is_null() || !function->is_compiled()) return;

  constant_function_ = function;
  AnalyzePossibleApiFunction(isolate, function);
}

void CallOptimization::AnalyzePossibleApiFunction(Isolate* isolate,
                                                  Handle<JSFunction> function) {
  if (!function->shared()->IsApiFunction()) return;
  Handle<FunctionTemplateInfo> info(function->shared()->get_api_func_data(),
                                    isolate);

  // Require a C++ callback.
  if (info->call_code()->IsUndefined(isolate)) return;
  api_call_info_ = handle(CallHandlerInfo::cast(info->call_code()), isolate);

  if (!info->signature()->IsUndefined(isolate)) {
    expected_receiver_type_ =
        handle(FunctionTemplateInfo::cast(info->signature()), isolate);
  }

  is_simple_api_call_ = true;
}
}  // namespace internal
}  // namespace v8
