mirror of
https://github.com/dart-lang/sdk
synced 2024-09-20 02:50:20 +00:00
Share intrinsification framework across architectures, started on instrinsification in the new compiler x64.
Review URL: https://chromiumcodereview.appspot.com//10035006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@6661 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
ff7d78833a
commit
64226e65ac
|
@ -23,7 +23,7 @@
|
|||
|
||||
namespace dart {
|
||||
|
||||
DEFINE_FLAG(bool, print_ast, false, "Print abstract syntax tree.");
|
||||
DECLARE_FLAG(bool, print_ast);
|
||||
DEFINE_FLAG(bool, print_scopes, false, "Print scopes of local variables.");
|
||||
DEFINE_FLAG(bool, trace_functions, false, "Trace entry of each function.");
|
||||
DEFINE_FLAG(bool, print_ic_in_optimized, false,
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
namespace dart {
|
||||
|
||||
DEFINE_FLAG(bool, print_ast, false, "Print abstract syntax tree.");
|
||||
DECLARE_FLAG(bool, print_ast);
|
||||
DEFINE_FLAG(bool, print_scopes, false, "Print scopes of local variables.");
|
||||
DEFINE_FLAG(bool, trace_functions, false, "Trace entry of each function.");
|
||||
DECLARE_FLAG(bool, enable_type_checks);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// 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 patching compiled code.
|
||||
|
@ -15,6 +15,7 @@ class Array;
|
|||
class Code;
|
||||
class ExternalLabel;
|
||||
class Function;
|
||||
class RawArray;
|
||||
class RawICData;
|
||||
class String;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace dart {
|
|||
|
||||
DEFINE_FLAG(bool, print_flow_graph, false, "Print the IR flow graph.");
|
||||
DECLARE_FLAG(bool, enable_type_checks);
|
||||
DECLARE_FLAG(bool, print_ast);
|
||||
DEFINE_FLAG(bool, print_ast, false, "Print abstract syntax tree.");
|
||||
|
||||
|
||||
FlowGraphBuilder::FlowGraphBuilder(const ParsedFunction& parsed_function)
|
||||
|
@ -2002,8 +2002,6 @@ void EffectGraphVisitor::VisitSequenceNode(SequenceNode* node) {
|
|||
// the captured parameters from the frame into the context.
|
||||
if (node == owner()->parsed_function().node_sequence()) {
|
||||
ASSERT(scope->context_level() == 1);
|
||||
const Immediate raw_null =
|
||||
Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
||||
const Function& function = owner()->parsed_function().function();
|
||||
const int num_params = function.NumberOfParameters();
|
||||
int param_frame_index =
|
||||
|
|
|
@ -11,7 +11,9 @@
|
|||
#include "vm/ast_printer.h"
|
||||
#include "vm/code_descriptors.h"
|
||||
#include "vm/code_generator.h"
|
||||
#include "vm/debugger.h"
|
||||
#include "vm/disassembler.h"
|
||||
#include "vm/intrinsifier.h"
|
||||
#include "vm/longjump.h"
|
||||
#include "vm/object_store.h"
|
||||
#include "vm/parser.h"
|
||||
|
@ -20,10 +22,14 @@
|
|||
namespace dart {
|
||||
|
||||
DECLARE_FLAG(bool, enable_type_checks);
|
||||
DECLARE_FLAG(bool, intrinsify);
|
||||
DECLARE_FLAG(bool, optimization_counter_threshold);
|
||||
DECLARE_FLAG(bool, print_ast);
|
||||
DECLARE_FLAG(bool, print_scopes);
|
||||
DECLARE_FLAG(bool, report_usage_count);
|
||||
DECLARE_FLAG(bool, trace_functions);
|
||||
|
||||
|
||||
FlowGraphCompiler::FlowGraphCompiler(
|
||||
Assembler* assembler,
|
||||
const ParsedFunction& parsed_function,
|
||||
|
@ -1519,9 +1525,88 @@ void FlowGraphCompiler::CopyParameters() {
|
|||
}
|
||||
|
||||
|
||||
bool FlowGraphCompiler::CanOptimize() {
|
||||
return
|
||||
!FLAG_report_usage_count &&
|
||||
(FLAG_optimization_counter_threshold >= 0) &&
|
||||
!Isolate::Current()->debugger()->IsActive();
|
||||
}
|
||||
|
||||
|
||||
void FlowGraphCompiler::IntrinsifyGetter() {
|
||||
// TOS: return address.
|
||||
// +1 : receiver.
|
||||
// Sequence node has one return node, its input is load field node.
|
||||
const SequenceNode& sequence_node = *parsed_function_.node_sequence();
|
||||
ASSERT(sequence_node.length() == 1);
|
||||
ASSERT(sequence_node.NodeAt(0)->IsReturnNode());
|
||||
const ReturnNode& return_node = *sequence_node.NodeAt(0)->AsReturnNode();
|
||||
ASSERT(return_node.value()->IsLoadInstanceFieldNode());
|
||||
const LoadInstanceFieldNode& load_node =
|
||||
*return_node.value()->AsLoadInstanceFieldNode();
|
||||
__ movq(RAX, Address(RSP, 1 * kWordSize));
|
||||
__ movq(RAX, FieldAddress(RAX, load_node.field().Offset()));
|
||||
__ ret();
|
||||
}
|
||||
|
||||
|
||||
void FlowGraphCompiler::IntrinsifySetter() {
|
||||
// TOS: return address.
|
||||
// +1 : value
|
||||
// +2 : receiver.
|
||||
// Sequence node has one store node and one return NULL node.
|
||||
const SequenceNode& sequence_node = *parsed_function_.node_sequence();
|
||||
ASSERT(sequence_node.length() == 2);
|
||||
ASSERT(sequence_node.NodeAt(0)->IsStoreInstanceFieldNode());
|
||||
ASSERT(sequence_node.NodeAt(1)->IsReturnNode());
|
||||
const StoreInstanceFieldNode& store_node =
|
||||
*sequence_node.NodeAt(0)->AsStoreInstanceFieldNode();
|
||||
__ movq(RAX, Address(RSP, 2 * kWordSize)); // Receiver.
|
||||
__ movq(RBX, Address(RSP, 1 * kWordSize)); // Value.
|
||||
__ StoreIntoObject(RAX, FieldAddress(RAX, store_node.field().Offset()), RBX);
|
||||
const Immediate raw_null =
|
||||
Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
||||
__ movq(RAX, raw_null);
|
||||
__ ret();
|
||||
}
|
||||
|
||||
|
||||
// Returns 'true' if code generation for this function is complete, i.e.,
|
||||
// no fall-through to regular code is needed.
|
||||
bool FlowGraphCompiler::TryIntrinsify() {
|
||||
if (!CanOptimize()) return false;
|
||||
// Intrinsification skips arguments checks, therefore disable if in checked
|
||||
// mode.
|
||||
if (FLAG_intrinsify && !FLAG_trace_functions && !FLAG_enable_type_checks) {
|
||||
if ((parsed_function_.function().kind() == RawFunction::kImplicitGetter)) {
|
||||
IntrinsifyGetter();
|
||||
return true;
|
||||
}
|
||||
if ((parsed_function_.function().kind() == RawFunction::kImplicitSetter)) {
|
||||
IntrinsifySetter();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Even if an intrinsified version of the function was successfully
|
||||
// generated, it may fall through to the non-intrinsified method body.
|
||||
if (!FLAG_trace_functions) {
|
||||
return Intrinsifier::Intrinsify(parsed_function_.function(), assembler_);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// TODO(srdjan): Investigate where to put the argument type checks for
|
||||
// checked mode.
|
||||
void FlowGraphCompiler::CompileGraph() {
|
||||
if (TryIntrinsify()) {
|
||||
// Make it patchable: code must have a minimum code size, nop(2) increases
|
||||
// the minimum code size appropriately.
|
||||
__ nop(2);
|
||||
__ int3();
|
||||
__ jmp(&StubCode::FixCallersTargetLabel());
|
||||
return;
|
||||
}
|
||||
// Specialized version of entry code from CodeGenerator::GenerateEntryCode.
|
||||
const Function& function = parsed_function_.function();
|
||||
|
||||
|
|
|
@ -120,6 +120,11 @@ class FlowGraphCompiler : public FlowGraphVisitor {
|
|||
|
||||
intptr_t StackSize() const;
|
||||
|
||||
bool TryIntrinsify();
|
||||
void IntrinsifyGetter();
|
||||
void IntrinsifySetter();
|
||||
static bool CanOptimize();
|
||||
|
||||
Assembler* assembler_;
|
||||
const ParsedFunction& parsed_function_;
|
||||
|
||||
|
|
77
runtime/vm/intrinsifier.cc
Normal file
77
runtime/vm/intrinsifier.cc
Normal file
|
@ -0,0 +1,77 @@
|
|||
// 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 corelib and matches the
|
||||
// test_class_name.
|
||||
const Library& core_lib = Library::Handle(Library::CoreLibrary());
|
||||
const Library& core_impl_lib = Library::Handle(Library::CoreImplLibrary());
|
||||
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(core_impl_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) {
|
||||
return CompareNames(test_class_name, function_class_name) &&
|
||||
CompareNames(test_function_name, function_name);
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Intrinsify(const Function& function, Assembler* assembler) {
|
||||
if (!FLAG_intrinsify) 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();
|
||||
// Only core library methods can be intrinsified.
|
||||
const Library& core_lib = Library::Handle(Library::CoreLibrary());
|
||||
const Library& core_impl_lib = Library::Handle(Library::CoreImplLibrary());
|
||||
if ((function_class.library() != core_lib.raw()) &&
|
||||
(function_class.library() != core_impl_lib.raw())) {
|
||||
return false;
|
||||
}
|
||||
#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
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// 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.
|
||||
|
@ -10,6 +10,73 @@
|
|||
|
||||
namespace dart {
|
||||
|
||||
// List of intrinsics: (class-name, function-name, intrinsification method).
|
||||
#define INTRINSIC_LIST(V) \
|
||||
V(IntegerImplementation, addFromInteger, Integer_addFromInteger) \
|
||||
V(IntegerImplementation, +, Integer_add) \
|
||||
V(IntegerImplementation, subFromInteger, Integer_subFromInteger) \
|
||||
V(IntegerImplementation, -, Integer_sub) \
|
||||
V(IntegerImplementation, mulFromInteger, Integer_mulFromInteger) \
|
||||
V(IntegerImplementation, *, Integer_mul) \
|
||||
V(IntegerImplementation, %, Integer_modulo) \
|
||||
V(IntegerImplementation, ~/, Integer_truncDivide) \
|
||||
V(IntegerImplementation, negate, Integer_negate) \
|
||||
V(IntegerImplementation, bitAndFromInteger, Integer_bitAndFromInteger) \
|
||||
V(IntegerImplementation, &, Integer_bitAnd) \
|
||||
V(IntegerImplementation, bitOrFromInteger, Integer_bitOrFromInteger) \
|
||||
V(IntegerImplementation, |, Integer_bitOr) \
|
||||
V(IntegerImplementation, bitXorFromInteger, Integer_bitXorFromInteger) \
|
||||
V(IntegerImplementation, ^, Integer_bitXor) \
|
||||
V(IntegerImplementation, greaterThanFromInteger, Integer_greaterThanFromInt) \
|
||||
V(IntegerImplementation, >, Integer_greaterThan) \
|
||||
V(IntegerImplementation, ==, Integer_equal) \
|
||||
V(IntegerImplementation, equalToInteger, Integer_equalToInteger) \
|
||||
V(IntegerImplementation, <, Integer_lessThan) \
|
||||
V(IntegerImplementation, <=, Integer_lessEqualThan) \
|
||||
V(IntegerImplementation, >=, Integer_greaterEqualThan) \
|
||||
V(IntegerImplementation, <<, Integer_shl) \
|
||||
V(IntegerImplementation, >>, Integer_sar) \
|
||||
V(Smi, ~, Smi_bitNegate) \
|
||||
V(Double, >, Double_greaterThan) \
|
||||
V(Double, >=, Double_greaterEqualThan) \
|
||||
V(Double, <, Double_lessThan) \
|
||||
V(Double, <=, Double_lessEqualThan) \
|
||||
V(Double, ==, Double_equal) \
|
||||
V(Double, +, Double_add) \
|
||||
V(Double, -, Double_sub) \
|
||||
V(Double, *, Double_mul) \
|
||||
V(Double, /, Double_div) \
|
||||
V(Double, toDouble, Double_toDouble) \
|
||||
V(Double, mulFromInteger, Double_mulFromInteger) \
|
||||
V(Double, Double.fromInteger, Double_fromInteger) \
|
||||
V(Double, isNaN, Double_isNaN) \
|
||||
V(Double, isNegative, Double_isNegative) \
|
||||
V(ObjectArray, ObjectArray., ObjectArray_Allocate) \
|
||||
V(ObjectArray, get:length, Array_getLength) \
|
||||
V(ObjectArray, [], Array_getIndexed) \
|
||||
V(ObjectArray, []=, Array_setIndexed) \
|
||||
V(GrowableObjectArray, GrowableObjectArray.fromObjectArray, GArray_Allocate) \
|
||||
V(GrowableObjectArray, get:length, GrowableArray_getLength) \
|
||||
V(GrowableObjectArray, get:capacity, GrowableArray_getCapacity) \
|
||||
V(GrowableObjectArray, [], GrowableArray_getIndexed) \
|
||||
V(GrowableObjectArray, []=, GrowableArray_setIndexed) \
|
||||
V(GrowableObjectArray, _setLength, GrowableArray_setLength) \
|
||||
V(GrowableObjectArray, set:data, GrowableArray_setData) \
|
||||
V(_ByteArrayBase, get:length, ByteArrayBase_getLength) \
|
||||
V(_ByteArrayBase, [], ByteArrayBase_getIndexed) \
|
||||
V(ImmutableArray, [], ImmutableArray_getIndexed) \
|
||||
V(ImmutableArray, get:length, ImmutableArray_getLength) \
|
||||
V(Math, sqrt, Math_sqrt) \
|
||||
V(Math, sin, Math_sin) \
|
||||
V(Math, cos, Math_cos) \
|
||||
V(Object, ==, Object_equal) \
|
||||
V(FixedSizeArrayIterator, next, FixedSizeArrayIterator_next) \
|
||||
V(FixedSizeArrayIterator, hasNext, FixedSizeArrayIterator_hasNext) \
|
||||
V(StringBase, get:length, String_getLength) \
|
||||
V(StringBase, charCodeAt, String_charCodeAt) \
|
||||
V(StringBase, hashCode, String_hashCode) \
|
||||
V(StringBase, isEmpty, String_isEmpty) \
|
||||
|
||||
// Forward declarations.
|
||||
class Assembler;
|
||||
class Function;
|
||||
|
@ -20,6 +87,13 @@ class Intrinsifier : public AllStatic {
|
|||
// completely and the code does not need to be generated (i.e., no slow
|
||||
// path possible).
|
||||
static bool Intrinsify(const Function& function, Assembler* assembler);
|
||||
|
||||
private:
|
||||
#define DECLARE_FUNCTION(test_class_name, test_function_name, destination) \
|
||||
static bool destination(Assembler* assembler);
|
||||
|
||||
INTRINSIC_LIST(DECLARE_FUNCTION)
|
||||
#undef DECLARE_FUNCTION
|
||||
};
|
||||
|
||||
} // namespace dart
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// 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.
|
||||
|
||||
|
@ -9,7 +9,322 @@
|
|||
|
||||
namespace dart {
|
||||
|
||||
bool Intrinsifier::Intrinsify(const Function& function, Assembler* assembler) {
|
||||
bool Intrinsifier::ObjectArray_Allocate(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Array_getLength(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::ImmutableArray_getLength(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Array_getIndexed(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::ImmutableArray_getIndexed(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Array_setIndexed(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::GArray_Allocate(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::GrowableArray_getLength(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::GrowableArray_getCapacity(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::GrowableArray_getIndexed(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::GrowableArray_setIndexed(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::GrowableArray_setLength(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::GrowableArray_setData(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::ByteArrayBase_getLength(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::ByteArrayBase_getIndexed(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_addFromInteger(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_add(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_subFromInteger(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_sub(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_mulFromInteger(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_mul(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_modulo(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_truncDivide(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_negate(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_bitAnd(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_bitOrFromInteger(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_bitOr(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_bitXorFromInteger(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_bitXor(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_shl(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_lessThan(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_greaterThanFromInt(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_greaterThan(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_lessEqualThan(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_greaterEqualThan(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_equalToInteger(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_equal(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_sar(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Smi_bitNegate(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Double_greaterThan(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Double_greaterEqualThan(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Double_lessThan(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Double_equal(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Double_lessEqualThan(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Double_toDouble(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Intrinsifier::Double_add(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Double_mul(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Double_sub(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Double_div(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Double_mulFromInteger(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Double_fromInteger(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Double_isNaN(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Double_isNegative(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Math_sqrt(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Math_sin(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Math_cos(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Object_equal(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::FixedSizeArrayIterator_next(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::FixedSizeArrayIterator_hasNext(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::String_getLength(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::String_charCodeAt(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::String_hashCode(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::String_isEmpty(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// 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.
|
||||
//
|
||||
|
@ -22,79 +22,12 @@
|
|||
|
||||
namespace dart {
|
||||
|
||||
DEFINE_FLAG(bool, intrinsify, true, "Instrinsify when possible");
|
||||
DECLARE_FLAG(bool, enable_type_checks);
|
||||
|
||||
// List of intrinsics: (class-name, function-name, intrinsification method).
|
||||
#define INTRINSIC_LIST(V) \
|
||||
V(IntegerImplementation, addFromInteger, Integer_addFromInteger) \
|
||||
V(IntegerImplementation, +, Integer_addFromInteger) \
|
||||
V(IntegerImplementation, subFromInteger, Integer_subFromInteger) \
|
||||
V(IntegerImplementation, -, Integer_sub) \
|
||||
V(IntegerImplementation, mulFromInteger, Integer_mulFromInteger) \
|
||||
V(IntegerImplementation, *, Integer_mulFromInteger) \
|
||||
V(IntegerImplementation, %, Integer_modulo) \
|
||||
V(IntegerImplementation, ~/, Integer_truncDivide) \
|
||||
V(IntegerImplementation, negate, Integer_negate) \
|
||||
V(IntegerImplementation, bitAndFromInteger, Integer_bitAndFromInteger) \
|
||||
V(IntegerImplementation, &, Integer_bitAndFromInteger) \
|
||||
V(IntegerImplementation, bitOrFromInteger, Integer_bitOrFromInteger) \
|
||||
V(IntegerImplementation, |, Integer_bitOrFromInteger) \
|
||||
V(IntegerImplementation, bitXorFromInteger, Integer_bitXorFromInteger) \
|
||||
V(IntegerImplementation, ^, Integer_bitXorFromInteger) \
|
||||
V(IntegerImplementation, greaterThanFromInteger, Integer_lessThan) \
|
||||
V(IntegerImplementation, >, Integer_greaterThan) \
|
||||
V(IntegerImplementation, ==, Integer_equalToInteger) \
|
||||
V(IntegerImplementation, equalToInteger, Integer_equalToInteger) \
|
||||
V(IntegerImplementation, <, Integer_lessThan) \
|
||||
V(IntegerImplementation, <=, Integer_lessEqualThan) \
|
||||
V(IntegerImplementation, >=, Integer_greaterEqualThan) \
|
||||
V(IntegerImplementation, <<, Integer_shl) \
|
||||
V(IntegerImplementation, >>, Integer_sar) \
|
||||
V(Smi, ~, Smi_bitNegate) \
|
||||
V(Double, >, Double_greaterThan) \
|
||||
V(Double, >=, Double_greaterEqualThan) \
|
||||
V(Double, <, Double_lessThan) \
|
||||
V(Double, <=, Double_lessEqualThan) \
|
||||
V(Double, ==, Double_equal) \
|
||||
V(Double, +, Double_add) \
|
||||
V(Double, -, Double_sub) \
|
||||
V(Double, *, Double_mul) \
|
||||
V(Double, /, Double_div) \
|
||||
V(Double, toDouble, Double_toDouble) \
|
||||
V(Double, mulFromInteger, Double_mulFromInteger) \
|
||||
V(Double, Double.fromInteger, Double_fromInteger) \
|
||||
V(Double, isNaN, Double_isNaN) \
|
||||
V(Double, isNegative, Double_isNegative) \
|
||||
V(ObjectArray, ObjectArray., ObjectArray_Allocate) \
|
||||
V(ObjectArray, get:length, Array_getLength) \
|
||||
V(ObjectArray, [], Array_getIndexed) \
|
||||
V(ObjectArray, []=, Array_setIndexed) \
|
||||
V(GrowableObjectArray, GrowableObjectArray.fromObjectArray, GArray_Allocate) \
|
||||
V(GrowableObjectArray, get:length, GrowableArray_getLength) \
|
||||
V(GrowableObjectArray, get:capacity, GrowableArray_getCapacity) \
|
||||
V(GrowableObjectArray, [], GrowableArray_getIndexed) \
|
||||
V(GrowableObjectArray, []=, GrowableArray_setIndexed) \
|
||||
V(GrowableObjectArray, _setLength, GrowableArray_setLength) \
|
||||
V(GrowableObjectArray, set:data, GrowableArray_setData) \
|
||||
V(_ByteArrayBase, get:length, ByteArrayBase_getLength) \
|
||||
V(_ByteArrayBase, [], ByteArrayBase_getIndexed) \
|
||||
V(ImmutableArray, [], Array_getIndexed) \
|
||||
V(ImmutableArray, get:length, Array_getLength) \
|
||||
V(Math, sqrt, Math_sqrt) \
|
||||
V(Math, sin, Math_sin) \
|
||||
V(Math, cos, Math_cos) \
|
||||
V(Object, ==, Object_equal) \
|
||||
V(FixedSizeArrayIterator, next, FixedSizeArrayIterator_next) \
|
||||
V(FixedSizeArrayIterator, hasNext, FixedSizeArrayIterator_hasNext) \
|
||||
V(StringBase, get:length, String_getLength) \
|
||||
V(StringBase, charCodeAt, String_charCodeAt) \
|
||||
V(StringBase, hashCode, String_hashCode) \
|
||||
V(StringBase, isEmpty, String_isEmpty) \
|
||||
|
||||
#define __ assembler->
|
||||
|
||||
static bool ObjectArray_Allocate(Assembler* assembler) {
|
||||
bool Intrinsifier::ObjectArray_Allocate(Assembler* assembler) {
|
||||
// This snippet of inlined code uses the following registers:
|
||||
// EAX, EBX, EDI
|
||||
// and the newly allocated object is returned in EAX.
|
||||
|
@ -193,7 +126,7 @@ static bool ObjectArray_Allocate(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
static bool Array_getLength(Assembler* assembler) {
|
||||
bool Intrinsifier::Array_getLength(Assembler* assembler) {
|
||||
__ movl(EAX, Address(ESP, + 1 * kWordSize));
|
||||
__ movl(EAX, FieldAddress(EAX, Array::length_offset()));
|
||||
__ ret();
|
||||
|
@ -201,7 +134,12 @@ static bool Array_getLength(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
static bool Array_getIndexed(Assembler* assembler) {
|
||||
bool Intrinsifier::ImmutableArray_getLength(Assembler* assembler) {
|
||||
return Array_getLength(assembler);
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Array_getIndexed(Assembler* assembler) {
|
||||
Label fall_through;
|
||||
__ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index.
|
||||
__ movl(EAX, Address(ESP, + 2 * kWordSize)); // Array.
|
||||
|
@ -220,6 +158,11 @@ static bool Array_getIndexed(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
bool Intrinsifier::ImmutableArray_getIndexed(Assembler* assembler) {
|
||||
return Array_getIndexed(assembler);
|
||||
}
|
||||
|
||||
|
||||
static intptr_t ComputeObjectArrayTypeArgumentsOffset() {
|
||||
const String& class_name = String::Handle(String::NewSymbol("ObjectArray"));
|
||||
const Class& cls = Class::Handle(
|
||||
|
@ -235,7 +178,7 @@ static intptr_t ComputeObjectArrayTypeArgumentsOffset() {
|
|||
|
||||
// Intrinsify only for Smi value and index. Non-smi values need a store buffer
|
||||
// update. Array length is always a Smi.
|
||||
static bool Array_setIndexed(Assembler* assembler) {
|
||||
bool Intrinsifier::Array_setIndexed(Assembler* assembler) {
|
||||
Label fall_through;
|
||||
if (FLAG_enable_type_checks) {
|
||||
const intptr_t type_args_field_offset =
|
||||
|
@ -310,7 +253,7 @@ static intptr_t GetOffsetForField(const char* class_name_p,
|
|||
|
||||
// Allocate a GrowableObjectArray using the backing array specified.
|
||||
// On stack: type argument (+2), data (+1), return-address (+0).
|
||||
static bool GArray_Allocate(Assembler* assembler) {
|
||||
bool Intrinsifier::GArray_Allocate(Assembler* assembler) {
|
||||
// This snippet of inlined code uses the following registers:
|
||||
// EAX, EBX
|
||||
// and the newly allocated object is returned in EAX.
|
||||
|
@ -378,7 +321,7 @@ static bool GArray_Allocate(Assembler* assembler) {
|
|||
|
||||
// Get length of growable object array.
|
||||
// On stack: growable array (+1), return-address (+0).
|
||||
static bool GrowableArray_getLength(Assembler* assembler) {
|
||||
bool Intrinsifier::GrowableArray_getLength(Assembler* assembler) {
|
||||
__ movl(EAX, Address(ESP, + 1 * kWordSize));
|
||||
__ movl(EAX, FieldAddress(EAX, GrowableObjectArray::length_offset()));
|
||||
__ ret();
|
||||
|
@ -388,7 +331,7 @@ static bool GrowableArray_getLength(Assembler* assembler) {
|
|||
|
||||
// Get capacity of growable object array.
|
||||
// On stack: growable array (+1), return-address (+0).
|
||||
static bool GrowableArray_getCapacity(Assembler* assembler) {
|
||||
bool Intrinsifier::GrowableArray_getCapacity(Assembler* assembler) {
|
||||
__ movl(EAX, Address(ESP, + 1 * kWordSize));
|
||||
__ movl(EAX, FieldAddress(EAX, GrowableObjectArray::data_offset()));
|
||||
__ movl(EAX, FieldAddress(EAX, Array::length_offset()));
|
||||
|
@ -399,7 +342,7 @@ static bool GrowableArray_getCapacity(Assembler* assembler) {
|
|||
|
||||
// Access growable object array at specified index.
|
||||
// On stack: growable array (+2), index (+1), return-address (+0).
|
||||
static bool GrowableArray_getIndexed(Assembler* assembler) {
|
||||
bool Intrinsifier::GrowableArray_getIndexed(Assembler* assembler) {
|
||||
Label fall_through;
|
||||
__ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index.
|
||||
__ movl(EAX, Address(ESP, + 2 * kWordSize)); // GrowableArray.
|
||||
|
@ -422,7 +365,7 @@ static bool GrowableArray_getIndexed(Assembler* assembler) {
|
|||
|
||||
// Set value into growable object array at specified index.
|
||||
// On stack: growable array (+3), index (+2), value (+1), return-address (+0).
|
||||
static bool GrowableArray_setIndexed(Assembler* assembler) {
|
||||
bool Intrinsifier::GrowableArray_setIndexed(Assembler* assembler) {
|
||||
if (FLAG_enable_type_checks) {
|
||||
return false;
|
||||
}
|
||||
|
@ -450,7 +393,7 @@ static bool GrowableArray_setIndexed(Assembler* assembler) {
|
|||
|
||||
// Set length of growable object array.
|
||||
// On stack: growable array (+2), length (+1), return-address (+0).
|
||||
static bool GrowableArray_setLength(Assembler* assembler) {
|
||||
bool Intrinsifier::GrowableArray_setLength(Assembler* assembler) {
|
||||
Label fall_through;
|
||||
__ movl(EAX, Address(ESP, + 2 * kWordSize));
|
||||
__ movl(EBX, Address(ESP, + 1 * kWordSize));
|
||||
|
@ -466,7 +409,7 @@ static bool GrowableArray_setLength(Assembler* assembler) {
|
|||
|
||||
// Set data of growable object array.
|
||||
// On stack: growable array (+2), data (+1), return-address (+0).
|
||||
static bool GrowableArray_setData(Assembler* assembler) {
|
||||
bool Intrinsifier::GrowableArray_setData(Assembler* assembler) {
|
||||
if (FLAG_enable_type_checks) {
|
||||
return false;
|
||||
}
|
||||
|
@ -479,7 +422,7 @@ static bool GrowableArray_setData(Assembler* assembler) {
|
|||
|
||||
|
||||
// Handles only class InternalByteArray.
|
||||
static bool ByteArrayBase_getLength(Assembler* assembler) {
|
||||
bool Intrinsifier::ByteArrayBase_getLength(Assembler* assembler) {
|
||||
ObjectStore* object_store = Isolate::Current()->object_store();
|
||||
Label fall_through;
|
||||
__ movl(EAX, Address(ESP, + 1 * kWordSize));
|
||||
|
@ -495,7 +438,7 @@ static bool ByteArrayBase_getLength(Assembler* assembler) {
|
|||
|
||||
|
||||
// Handles only class InternalByteArray.
|
||||
static bool ByteArrayBase_getIndexed(Assembler* assembler) {
|
||||
bool Intrinsifier::ByteArrayBase_getIndexed(Assembler* assembler) {
|
||||
ObjectStore* object_store = Isolate::Current()->object_store();
|
||||
Label fall_through;
|
||||
__ movl(EAX, Address(ESP, + 2 * kWordSize)); // Array.
|
||||
|
@ -533,7 +476,7 @@ static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) {
|
|||
}
|
||||
|
||||
|
||||
static bool Integer_addFromInteger(Assembler* assembler) {
|
||||
bool Intrinsifier::Integer_addFromInteger(Assembler* assembler) {
|
||||
Label fall_through;
|
||||
TestBothArgumentsSmis(assembler, &fall_through);
|
||||
__ addl(EAX, Address(ESP, + 2 * kWordSize));
|
||||
|
@ -545,7 +488,12 @@ static bool Integer_addFromInteger(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
static bool Integer_subFromInteger(Assembler* assembler) {
|
||||
bool Intrinsifier::Integer_add(Assembler* assembler) {
|
||||
return Integer_addFromInteger(assembler);
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_subFromInteger(Assembler* assembler) {
|
||||
Label fall_through;
|
||||
TestBothArgumentsSmis(assembler, &fall_through);
|
||||
__ subl(EAX, Address(ESP, + 2 * kWordSize));
|
||||
|
@ -557,7 +505,7 @@ static bool Integer_subFromInteger(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
static bool Integer_sub(Assembler* assembler) {
|
||||
bool Intrinsifier::Integer_sub(Assembler* assembler) {
|
||||
Label fall_through;
|
||||
TestBothArgumentsSmis(assembler, &fall_through);
|
||||
__ movl(EBX, EAX);
|
||||
|
@ -572,7 +520,7 @@ static bool Integer_sub(Assembler* assembler) {
|
|||
|
||||
|
||||
|
||||
static bool Integer_mulFromInteger(Assembler* assembler) {
|
||||
bool Intrinsifier::Integer_mulFromInteger(Assembler* assembler) {
|
||||
Label fall_through;
|
||||
TestBothArgumentsSmis(assembler, &fall_through);
|
||||
ASSERT(kSmiTag == 0); // Adjust code below if not the case.
|
||||
|
@ -586,9 +534,14 @@ static bool Integer_mulFromInteger(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_mul(Assembler* assembler) {
|
||||
return Integer_mulFromInteger(assembler);
|
||||
}
|
||||
|
||||
|
||||
// Simple implementation: for positive dividend values greater than divisor,
|
||||
// return dividend.
|
||||
static bool Integer_modulo(Assembler* assembler) {
|
||||
bool Intrinsifier::Integer_modulo(Assembler* assembler) {
|
||||
Label fall_through, return_zero;
|
||||
TestBothArgumentsSmis(assembler, &fall_through);
|
||||
// EAX: right argument (divisor)
|
||||
|
@ -611,7 +564,7 @@ static bool Integer_modulo(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
static bool Integer_truncDivide(Assembler* assembler) {
|
||||
bool Intrinsifier::Integer_truncDivide(Assembler* assembler) {
|
||||
Label fall_through;
|
||||
TestBothArgumentsSmis(assembler, &fall_through);
|
||||
// EAX: right argument (divisor)
|
||||
|
@ -636,7 +589,7 @@ static bool Integer_truncDivide(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
static bool Integer_negate(Assembler* assembler) {
|
||||
bool Intrinsifier::Integer_negate(Assembler* assembler) {
|
||||
Label fall_through;
|
||||
__ movl(EAX, Address(ESP, + 1 * kWordSize));
|
||||
__ testl(EAX, Immediate(kSmiTagMask));
|
||||
|
@ -650,7 +603,7 @@ static bool Integer_negate(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
static bool Integer_bitAndFromInteger(Assembler* assembler) {
|
||||
bool Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler) {
|
||||
Label fall_through;
|
||||
TestBothArgumentsSmis(assembler, &fall_through);
|
||||
__ movl(EBX, Address(ESP, + 2 * kWordSize));
|
||||
|
@ -662,7 +615,12 @@ static bool Integer_bitAndFromInteger(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
static bool Integer_bitOrFromInteger(Assembler* assembler) {
|
||||
bool Intrinsifier::Integer_bitAnd(Assembler* assembler) {
|
||||
return Integer_bitAndFromInteger(assembler);
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_bitOrFromInteger(Assembler* assembler) {
|
||||
Label fall_through;
|
||||
TestBothArgumentsSmis(assembler, &fall_through);
|
||||
__ movl(EBX, Address(ESP, + 2 * kWordSize));
|
||||
|
@ -674,7 +632,12 @@ static bool Integer_bitOrFromInteger(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
static bool Integer_bitXorFromInteger(Assembler* assembler) {
|
||||
bool Intrinsifier::Integer_bitOr(Assembler* assembler) {
|
||||
return Integer_bitOrFromInteger(assembler);
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_bitXorFromInteger(Assembler* assembler) {
|
||||
Label fall_through;
|
||||
TestBothArgumentsSmis(assembler, &fall_through);
|
||||
__ movl(EBX, Address(ESP, + 2 * kWordSize));
|
||||
|
@ -686,7 +649,12 @@ static bool Integer_bitXorFromInteger(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
static bool Integer_shl(Assembler* assembler) {
|
||||
bool Intrinsifier::Integer_bitXor(Assembler* assembler) {
|
||||
return Integer_bitXorFromInteger(assembler);
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_shl(Assembler* assembler) {
|
||||
ASSERT(kSmiTagShift == 1);
|
||||
ASSERT(kSmiTag == 0);
|
||||
Label fall_through, overflow;
|
||||
|
@ -757,28 +725,33 @@ static bool CompareIntegers(Assembler* assembler, Condition true_condition) {
|
|||
}
|
||||
|
||||
|
||||
static bool Integer_lessThan(Assembler* assembler) {
|
||||
bool Intrinsifier::Integer_lessThan(Assembler* assembler) {
|
||||
return CompareIntegers(assembler, LESS);
|
||||
}
|
||||
|
||||
|
||||
static bool Integer_greaterThan(Assembler* assembler) {
|
||||
bool Intrinsifier::Integer_greaterThanFromInt(Assembler* assembler) {
|
||||
return CompareIntegers(assembler, LESS);
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_greaterThan(Assembler* assembler) {
|
||||
return CompareIntegers(assembler, GREATER);
|
||||
}
|
||||
|
||||
|
||||
static bool Integer_lessEqualThan(Assembler* assembler) {
|
||||
bool Intrinsifier::Integer_lessEqualThan(Assembler* assembler) {
|
||||
return CompareIntegers(assembler, LESS_EQUAL);
|
||||
}
|
||||
|
||||
|
||||
static bool Integer_greaterEqualThan(Assembler* assembler) {
|
||||
bool Intrinsifier::Integer_greaterEqualThan(Assembler* assembler) {
|
||||
return CompareIntegers(assembler, GREATER_EQUAL);
|
||||
}
|
||||
|
||||
|
||||
// This is called for Smi, Mint and Bigint receivers. Bigints are not handled.
|
||||
static bool Integer_equalToInteger(Assembler* assembler) {
|
||||
bool Intrinsifier::Integer_equalToInteger(Assembler* assembler) {
|
||||
Label fall_through, true_label, check_for_mint;
|
||||
const Bool& bool_true = Bool::ZoneHandle(Bool::True());
|
||||
const Bool& bool_false = Bool::ZoneHandle(Bool::False());
|
||||
|
@ -834,7 +807,12 @@ static bool Integer_equalToInteger(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
static bool Integer_sar(Assembler* assembler) {
|
||||
bool Intrinsifier::Integer_equal(Assembler* assembler) {
|
||||
return Integer_equalToInteger(assembler);
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_sar(Assembler* assembler) {
|
||||
Label fall_through, shift_count_ok;
|
||||
TestBothArgumentsSmis(assembler, &fall_through);
|
||||
// Can destroy ECX since we are not falling through.
|
||||
|
@ -861,7 +839,7 @@ static bool Integer_sar(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
static bool Smi_bitNegate(Assembler* assembler) {
|
||||
bool Intrinsifier::Smi_bitNegate(Assembler* assembler) {
|
||||
Label fall_through;
|
||||
__ movl(EAX, Address(ESP, + 1 * kWordSize)); // Index.
|
||||
__ testl(EAX, Immediate(kSmiTagMask));
|
||||
|
@ -925,36 +903,36 @@ static bool CompareDoubles(Assembler* assembler, Condition true_condition) {
|
|||
|
||||
|
||||
// arg0 is Double, arg1 is unknown.
|
||||
static bool Double_greaterThan(Assembler* assembler) {
|
||||
bool Intrinsifier::Double_greaterThan(Assembler* assembler) {
|
||||
return CompareDoubles(assembler, ABOVE);
|
||||
}
|
||||
|
||||
|
||||
// arg0 is Double, arg1 is unknown.
|
||||
static bool Double_greaterEqualThan(Assembler* assembler) {
|
||||
bool Intrinsifier::Double_greaterEqualThan(Assembler* assembler) {
|
||||
return CompareDoubles(assembler, ABOVE_EQUAL);
|
||||
}
|
||||
|
||||
|
||||
// arg0 is Double, arg1 is unknown.
|
||||
static bool Double_lessThan(Assembler* assembler) {
|
||||
bool Intrinsifier::Double_lessThan(Assembler* assembler) {
|
||||
return CompareDoubles(assembler, BELOW);
|
||||
}
|
||||
|
||||
|
||||
// arg0 is Double, arg1 is unknown.
|
||||
static bool Double_equal(Assembler* assembler) {
|
||||
bool Intrinsifier::Double_equal(Assembler* assembler) {
|
||||
return CompareDoubles(assembler, EQUAL);
|
||||
}
|
||||
|
||||
|
||||
// arg0 is Double, arg1 is unknown.
|
||||
static bool Double_lessEqualThan(Assembler* assembler) {
|
||||
bool Intrinsifier::Double_lessEqualThan(Assembler* assembler) {
|
||||
return CompareDoubles(assembler, BELOW_EQUAL);
|
||||
}
|
||||
|
||||
|
||||
static bool Double_toDouble(Assembler* assembler) {
|
||||
bool Intrinsifier::Double_toDouble(Assembler* assembler) {
|
||||
__ movl(EAX, Address(ESP, + 1 * kWordSize));
|
||||
__ ret();
|
||||
return true;
|
||||
|
@ -992,28 +970,28 @@ static bool DoubleArithmeticOperations(Assembler* assembler, Token::Kind kind) {
|
|||
}
|
||||
|
||||
|
||||
static bool Double_add(Assembler* assembler) {
|
||||
bool Intrinsifier::Double_add(Assembler* assembler) {
|
||||
return DoubleArithmeticOperations(assembler, Token::kADD);
|
||||
}
|
||||
|
||||
|
||||
static bool Double_mul(Assembler* assembler) {
|
||||
bool Intrinsifier::Double_mul(Assembler* assembler) {
|
||||
return DoubleArithmeticOperations(assembler, Token::kMUL);
|
||||
}
|
||||
|
||||
|
||||
static bool Double_sub(Assembler* assembler) {
|
||||
bool Intrinsifier::Double_sub(Assembler* assembler) {
|
||||
return DoubleArithmeticOperations(assembler, Token::kSUB);
|
||||
}
|
||||
|
||||
|
||||
static bool Double_div(Assembler* assembler) {
|
||||
bool Intrinsifier::Double_div(Assembler* assembler) {
|
||||
return DoubleArithmeticOperations(assembler, Token::kDIV);
|
||||
}
|
||||
|
||||
|
||||
// Left is double right is integer (bigint or Smi)
|
||||
static bool Double_mulFromInteger(Assembler* assembler) {
|
||||
bool Intrinsifier::Double_mulFromInteger(Assembler* assembler) {
|
||||
Label fall_through;
|
||||
// Only Smi-s allowed.
|
||||
__ movl(EAX, Address(ESP, + 1 * kWordSize));
|
||||
|
@ -1040,7 +1018,7 @@ static bool Double_mulFromInteger(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
static bool Double_fromInteger(Assembler* assembler) {
|
||||
bool Intrinsifier::Double_fromInteger(Assembler* assembler) {
|
||||
Label fall_through;
|
||||
__ movl(EAX, Address(ESP, +1 * kWordSize));
|
||||
__ testl(EAX, Immediate(kSmiTagMask));
|
||||
|
@ -1063,7 +1041,7 @@ static bool Double_fromInteger(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
static bool Double_isNaN(Assembler* assembler) {
|
||||
bool Intrinsifier::Double_isNaN(Assembler* assembler) {
|
||||
const Bool& bool_true = Bool::ZoneHandle(Bool::True());
|
||||
const Bool& bool_false = Bool::ZoneHandle(Bool::False());
|
||||
Label is_true;
|
||||
|
@ -1080,7 +1058,7 @@ static bool Double_isNaN(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
static bool Double_isNegative(Assembler* assembler) {
|
||||
bool Intrinsifier::Double_isNegative(Assembler* assembler) {
|
||||
const Bool& bool_true = Bool::ZoneHandle(Bool::True());
|
||||
const Bool& bool_false = Bool::ZoneHandle(Bool::False());
|
||||
Label is_false, is_true, is_zero;
|
||||
|
@ -1108,7 +1086,7 @@ static bool Double_isNegative(Assembler* assembler) {
|
|||
|
||||
|
||||
// Argument type is not known
|
||||
static bool Math_sqrt(Assembler* assembler) {
|
||||
bool Intrinsifier::Math_sqrt(Assembler* assembler) {
|
||||
Label fall_through, is_smi, double_op;
|
||||
TestLastArgumentIsDouble(assembler, &is_smi, &fall_through);
|
||||
// Argument is double and is in EAX, class in EBX.
|
||||
|
@ -1180,20 +1158,20 @@ static void EmitTrigonometric(Assembler* assembler,
|
|||
}
|
||||
|
||||
|
||||
static bool Math_sin(Assembler* assembler) {
|
||||
bool Intrinsifier::Math_sin(Assembler* assembler) {
|
||||
EmitTrigonometric(assembler, kSine);
|
||||
return false; // Compile method for slow case.
|
||||
}
|
||||
|
||||
|
||||
static bool Math_cos(Assembler* assembler) {
|
||||
bool Intrinsifier::Math_cos(Assembler* assembler) {
|
||||
EmitTrigonometric(assembler, kCosine);
|
||||
return false; // Compile method for slow case.
|
||||
}
|
||||
|
||||
|
||||
// Identity comparison.
|
||||
static bool Object_equal(Assembler* assembler) {
|
||||
bool Intrinsifier::Object_equal(Assembler* assembler) {
|
||||
Label is_true;
|
||||
const Bool& bool_true = Bool::ZoneHandle(Bool::True());
|
||||
const Bool& bool_false = Bool::ZoneHandle(Bool::False());
|
||||
|
@ -1219,7 +1197,7 @@ static const char* kFixedSizeArrayIteratorClassName = "FixedSizeArrayIterator";
|
|||
// Intrinsify: return _array[_pos++];
|
||||
// TODO(srdjan): Throw a 'NoMoreElementsException' exception if the iterator
|
||||
// has no more elements.
|
||||
static bool FixedSizeArrayIterator_next(Assembler* assembler) {
|
||||
bool Intrinsifier::FixedSizeArrayIterator_next(Assembler* assembler) {
|
||||
Label fall_through;
|
||||
intptr_t array_offset =
|
||||
GetOffsetForField(kFixedSizeArrayIteratorClassName, "_array");
|
||||
|
@ -1261,7 +1239,7 @@ static bool FixedSizeArrayIterator_next(Assembler* assembler) {
|
|||
// bool hasNext() {
|
||||
// return _length > _pos;
|
||||
// }
|
||||
static bool FixedSizeArrayIterator_hasNext(Assembler* assembler) {
|
||||
bool Intrinsifier::FixedSizeArrayIterator_hasNext(Assembler* assembler) {
|
||||
Label fall_through, is_true;
|
||||
const Bool& bool_true = Bool::ZoneHandle(Bool::True());
|
||||
const Bool& bool_false = Bool::ZoneHandle(Bool::False());
|
||||
|
@ -1288,7 +1266,7 @@ static bool FixedSizeArrayIterator_hasNext(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
static bool String_getLength(Assembler* assembler) {
|
||||
bool Intrinsifier::String_getLength(Assembler* assembler) {
|
||||
__ movl(EAX, Address(ESP, + 1 * kWordSize)); // String object.
|
||||
__ movl(EAX, FieldAddress(EAX, String::length_offset()));
|
||||
__ ret();
|
||||
|
@ -1297,7 +1275,7 @@ static bool String_getLength(Assembler* assembler) {
|
|||
|
||||
|
||||
// TODO(srdjan): Implement for two and four byte strings as well.
|
||||
static bool String_charCodeAt(Assembler* assembler) {
|
||||
bool Intrinsifier::String_charCodeAt(Assembler* assembler) {
|
||||
ObjectStore* object_store = Isolate::Current()->object_store();
|
||||
Label fall_through;
|
||||
__ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index.
|
||||
|
@ -1321,7 +1299,7 @@ static bool String_charCodeAt(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
static bool String_hashCode(Assembler* assembler) {
|
||||
bool Intrinsifier::String_hashCode(Assembler* assembler) {
|
||||
Label fall_through;
|
||||
__ movl(EAX, Address(ESP, + 1 * kWordSize)); // String object.
|
||||
__ movl(EAX, FieldAddress(EAX, String::hash_offset()));
|
||||
|
@ -1334,7 +1312,7 @@ static bool String_hashCode(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
static bool String_isEmpty(Assembler* assembler) {
|
||||
bool Intrinsifier::String_isEmpty(Assembler* assembler) {
|
||||
Label is_true;
|
||||
const Bool& bool_true = Bool::ZoneHandle(Bool::True());
|
||||
const Bool& bool_false = Bool::ZoneHandle(Bool::False());
|
||||
|
@ -1352,70 +1330,6 @@ static bool String_isEmpty(Assembler* assembler) {
|
|||
}
|
||||
|
||||
#undef __
|
||||
|
||||
|
||||
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 corelib and matches the
|
||||
// test_class_name.
|
||||
const Library& core_lib = Library::Handle(Library::CoreLibrary());
|
||||
const Library& core_impl_lib = Library::Handle(Library::CoreImplLibrary());
|
||||
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(core_impl_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) {
|
||||
return CompareNames(test_class_name, function_class_name) &&
|
||||
CompareNames(test_function_name, function_name);
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Intrinsify(const Function& function, Assembler* assembler) {
|
||||
if (!FLAG_intrinsify) 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();
|
||||
// Only core library methods can be intrinsified.
|
||||
const Library& core_lib = Library::Handle(Library::CoreLibrary());
|
||||
const Library& core_impl_lib = Library::Handle(Library::CoreImplLibrary());
|
||||
if ((function_class.library() != core_lib.raw()) &&
|
||||
(function_class.library() != core_impl_lib.raw())) {
|
||||
return false;
|
||||
}
|
||||
#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
|
||||
|
||||
#endif // defined TARGET_ARCH_IA32
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
||||
// 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.
|
||||
|
||||
|
@ -8,8 +8,322 @@
|
|||
#include "vm/intrinsifier.h"
|
||||
|
||||
namespace dart {
|
||||
bool Intrinsifier::ObjectArray_Allocate(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Intrinsifier::Intrinsify(const Function& function, Assembler* assembler) {
|
||||
|
||||
bool Intrinsifier::Array_getLength(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::ImmutableArray_getLength(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Array_getIndexed(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::ImmutableArray_getIndexed(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Array_setIndexed(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::GArray_Allocate(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::GrowableArray_getLength(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::GrowableArray_getCapacity(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::GrowableArray_getIndexed(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::GrowableArray_setIndexed(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::GrowableArray_setLength(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::GrowableArray_setData(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::ByteArrayBase_getLength(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::ByteArrayBase_getIndexed(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_addFromInteger(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_add(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_subFromInteger(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_sub(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_mulFromInteger(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_mul(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_modulo(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_truncDivide(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_negate(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_bitAnd(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_bitOrFromInteger(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_bitOr(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_bitXorFromInteger(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_bitXor(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_shl(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_lessThan(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_greaterThanFromInt(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_greaterThan(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_lessEqualThan(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_greaterEqualThan(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_equalToInteger(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_equal(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Integer_sar(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Smi_bitNegate(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Double_greaterThan(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Double_greaterEqualThan(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Double_lessThan(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Double_equal(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Double_lessEqualThan(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Double_toDouble(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Intrinsifier::Double_add(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Double_mul(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Double_sub(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Double_div(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Double_mulFromInteger(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Double_fromInteger(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Double_isNaN(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Double_isNegative(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Math_sqrt(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Math_sin(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Math_cos(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::Object_equal(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::FixedSizeArrayIterator_next(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::FixedSizeArrayIterator_hasNext(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::String_getLength(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::String_charCodeAt(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::String_hashCode(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Intrinsifier::String_isEmpty(Assembler* assembler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -152,6 +152,7 @@
|
|||
'intermediate_language.h',
|
||||
'intermediate_language_test.cc',
|
||||
'intrinsifier.h',
|
||||
'intrinsifier.cc',
|
||||
'intrinsifier_arm.cc',
|
||||
'intrinsifier_ia32.cc',
|
||||
'intrinsifier_x64.cc',
|
||||
|
|
Loading…
Reference in a new issue