// 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(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(Handle<JSFunction>::cast(function));
  } else if (function->IsFunctionTemplateInfo()) {
    Initialize(Handle<FunctionTemplateInfo>::cast(function));
  }
}

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()) {
    Handle<JSObject> prototype(JSObject::cast(object_map->prototype()));
    object_map = handle(prototype->map());
    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());
  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(
    Handle<FunctionTemplateInfo> function_template_info) {
  Isolate* isolate = function_template_info->GetIsolate();
  if (function_template_info->call_code()->IsUndefined(isolate)) return;
  api_call_info_ =
      handle(CallHandlerInfo::cast(function_template_info->call_code()));

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

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

  constant_function_ = function;
  AnalyzePossibleApiFunction(function);
}


void CallOptimization::AnalyzePossibleApiFunction(Handle<JSFunction> function) {
  if (!function->shared()->IsApiFunction()) return;
  Isolate* isolate = function->GetIsolate();
  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
