blob: 59adb5cace67d88e6bd8d5bed0ae5d7e5e1b2977 [file] [log] [blame]
// Copyright (c) 2012, 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.
// Class for intrinsifying functions.
#include "vm/intrinsifier.h"
#include "vm/flags.h"
#include "vm/object.h"
namespace dart {
DEFINE_FLAG(bool, intrinsify, true, "Instrinsify when possible");
static bool CompareNames(const char* test_name, const char* name) {
if (strcmp(test_name, name) == 0) {
return true;
}
if ((name[0] == '_') && (test_name[0] == '_')) {
// Check if the private class is member of core or scalarlist and matches
// the test_class_name.
const Library& core_lib = Library::Handle(Library::CoreLibrary());
const Library& scalarlist_lib =
Library::Handle(Library::ScalarlistLibrary());
String& test_str = String::Handle(String::New(test_name));
String& test_str_with_key = String::Handle();
test_str_with_key =
String::Concat(test_str, String::Handle(core_lib.private_key()));
if (strcmp(test_str_with_key.ToCString(), name) == 0) {
return true;
}
test_str_with_key =
String::Concat(test_str, String::Handle(scalarlist_lib.private_key()));
if (strcmp(test_str_with_key.ToCString(), name) == 0) {
return true;
}
}
return false;
}
// Returns true if the function matches function_name and class_name, with
// special recognition of corelib private classes.
static bool TestFunction(const Function& function,
const char* function_class_name,
const char* function_name,
const char* test_class_name,
const char* test_function_name) {
// If test_function_name starts with a '.' we use that to indicate
// that it is a named constructor in the class. Therefore, if
// the class matches and the rest of the method name starting with
// the dot matches, we have found a match.
if (test_function_name[0] == '.') {
function_name = strstr(function_name, ".");
if (function_name == NULL) {
return false;
}
}
return CompareNames(test_class_name, function_class_name) &&
CompareNames(test_function_name, function_name);
}
bool Intrinsifier::CanIntrinsify(const Function& function) {
if (!FLAG_intrinsify) return false;
if (function.IsClosureFunction()) return false;
// Intrinsic kind is set lazily below.
if (function.intrinsic_kind() == Function::kIsIntrinsic) return true;
if (function.intrinsic_kind() == Function::kIsNotIntrinsic) return false;
// Closure functions may have different arguments.
const char* function_name = String::Handle(function.name()).ToCString();
const Class& function_class = Class::Handle(function.Owner());
// Only core, math and scalarlist library methods can be intrinsified.
if ((function_class.library() != Library::CoreLibrary()) &&
(function_class.library() != Library::MathLibrary()) &&
(function_class.library() != Library::ScalarlistLibrary())) {
return false;
}
const char* class_name = String::Handle(function_class.Name()).ToCString();
#define FIND_INTRINSICS(test_class_name, test_function_name, destination) \
if (TestFunction(function, \
class_name, function_name, \
#test_class_name, #test_function_name)) { \
function.set_intrinsic_kind(Function::kIsIntrinsic); \
return true; \
} \
INTRINSIC_LIST(FIND_INTRINSICS);
#undef FIND_INTRINSICS
function.set_intrinsic_kind(Function::kIsNotIntrinsic);
return false;
}
bool Intrinsifier::Intrinsify(const Function& function, Assembler* assembler) {
if (!CanIntrinsify(function)) return false;
const char* function_name = String::Handle(function.name()).ToCString();
const Class& function_class = Class::Handle(function.Owner());
const char* class_name = String::Handle(function_class.Name()).ToCString();
#define FIND_INTRINSICS(test_class_name, test_function_name, destination) \
if (TestFunction(function, \
class_name, function_name, \
#test_class_name, #test_function_name)) { \
return destination(assembler); \
} \
INTRINSIC_LIST(FIND_INTRINSICS);
#undef FIND_INTRINSICS
return false;
}
} // namespace dart