// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "include/dart_api.h"

#include "platform/globals.h"

#include "vm/compiler/backend/slot.h"
#include "vm/compiler/compiler_state.h"
#include "vm/object.h"
#include "vm/parser.h"
#include "vm/symbols.h"
#include "vm/unit_test.h"

namespace dart {

// This is a regression test for b/121271056: there might be a race between
// background compiler and mutator where mutator changes guarded state of
// the field after Slot was created from it. A situation is possible where we
// have a clone of a field with its guarded state set to unknown, however
// Slot::Get for this field returns a Slot created from the previous clone of
// the same field with a known guarded state. In this case we must add *old*
// clone from which the Slot was created to guarded fields and not the new
// clone, because new clone has no guarded state to begin with and thus
// ParsedFunction::AddToGuardedFields(...) would simply ignore it.
// Such slots with inconsistent guarded state that are not in the current
// list of guarded fields arise due to unsuccessful inlining attempts.
// If we built and discard the graph, then guarded fields associated with
// that graph are also discarded. However the slot itself stays behind in
// the global cache.
// Adding old clone would lead to correct rejection of the compilation
// attempt because Slot type information is different from the current guarded
// state of the field.
TEST_CASE(SlotFromGuardedField) {
  if (!FLAG_use_field_guards) {
    return;
  }

  TransitionNativeToVM transition(thread);
  Zone* zone = thread->zone();

  // Setup: create dummy class, function and a field.
  const Class& dummy_class = Class::Handle(Class::New(
      Library::Handle(), String::Handle(Symbols::New(thread, "DummyClass")),
      Script::Handle(), TokenPosition::kNoSource));
  dummy_class.set_is_synthesized_class_unsafe();

  const FunctionType& signature = FunctionType::ZoneHandle(FunctionType::New());
  const Function& dummy_function = Function::ZoneHandle(
      Function::New(signature, String::Handle(Symbols::New(thread, "foo")),
                    UntaggedFunction::kRegularFunction, false, false, false,
                    false, false, dummy_class, TokenPosition::kMinSource));

  const Field& field = Field::Handle(
      Field::New(String::Handle(Symbols::New(thread, "field")),
                 /*is_static=*/false, /*is_final=*/false, /*is_const=*/false,
                 /*is_reflectable=*/true, /*is_late=*/false, dummy_class,
                 Object::dynamic_type(), TokenPosition::kMinSource,
                 TokenPosition::kMinSource));

  // Set non-trivial guarded state on the field.
  field.set_guarded_cid_unsafe(kSmiCid);
  field.set_is_nullable_unsafe(false);

  // Enter compiler state.
  CompilerState compiler_state(thread, /*is_aot=*/false,
                               /*is_optimizing=*/true);

  const Field& field_clone_1 = Field::ZoneHandle(field.CloneFromOriginal());
  const Field& field_clone_2 = Field::ZoneHandle(field.CloneFromOriginal());

  // Check that Slot::Get() returns correctly canonicalized and configured
  // slot that matches properties of the field.
  ParsedFunction* parsed_function =
      new (zone) ParsedFunction(thread, dummy_function);
  const Slot& slot1 = Slot::Get(field_clone_1, parsed_function);
  const Slot& slot2 = Slot::Get(field_clone_2, parsed_function);
  EXPECT_EQ(&slot1, &slot2);
  EXPECT(slot1.is_guarded_field());
  EXPECT(!slot1.type().is_nullable());
  EXPECT_EQ(kSmiCid, slot1.type().ToCid());

  // Check that the field was added (once) to the list of guarded fields.
  EXPECT_EQ(1, parsed_function->guarded_fields()->Length());
  EXPECT(parsed_function->guarded_fields()->HasKey(&field_clone_1));

  // Change the guarded state of the field to "unknown" - emulating concurrent
  // modification of the guarded state in mutator) and create a new clone of
  // the field.
  field.set_guarded_cid_unsafe(kDynamicCid);
  field.set_is_nullable_unsafe(true);
  const Field& field_clone_3 = Field::ZoneHandle(field.CloneFromOriginal());

  // Slot::Get must return the same slot and add the field from which it
  // was created to the guarded fields list.
  ParsedFunction* parsed_function2 =
      new (zone) ParsedFunction(thread, dummy_function);
  const Slot& slot3 = Slot::Get(field_clone_3, parsed_function2);
  EXPECT_EQ(&slot1, &slot3);
  EXPECT_EQ(1, parsed_function2->guarded_fields()->Length());
  EXPECT(parsed_function2->guarded_fields()->HasKey(&field_clone_1));
}

}  // namespace dart
