blob: 94fee57cff1a472bdbc2c94b6317a10685e6691d [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.
#include "platform/assert.h"
#include "vm/class_finalizer.h"
#include "vm/compiler.h"
#include "vm/object.h"
#include "vm/pages.h"
#include "vm/stack_frame.h"
#include "vm/symbols.h"
#include "vm/unit_test.h"
namespace dart {
TEST_CASE(FindCodeObject) {
#if defined(TARGET_ARCH_IA32)
const int kLoopCount = 50000;
#elif defined(TARGET_ARCH_X64)
const int kLoopCount = 25000;
#elif defined(TARGET_ARCH_MIPS)
// TODO(zra): Increase after we implement far branches on MIPS.
const int kLoopCount = 1818;
#else
const int kLoopCount = 20000;
#endif
const int kScriptSize = 512 * KB;
const int kNumFunctions = 1024;
char scriptChars[kScriptSize];
String& url = String::Handle(String::New("dart-test:FindCodeObject"));
String& source = String::Handle();
Script& script = Script::Handle();
Library& lib = Library::Handle();
Class& clsA = Class::Handle();
Class& clsB = Class::Handle();
String& function_name = String::Handle();
Function& function = Function::Handle();
char buffer[256];
// Get access to the code index table.
Isolate* isolate = Isolate::Current();
ASSERT(isolate != NULL);
lib = Library::CoreLibrary();
// Load up class A with 1024 functions.
int written = OS::SNPrint(scriptChars, kScriptSize, "class A {");
for (int i = 0; i < kNumFunctions; i++) {
OS::SNPrint(buffer,
256,
"static foo%d([int i=1,int j=2,int k=3]){return i+j+k;}", i);
written += OS::SNPrint((scriptChars + written),
(kScriptSize - written),
"%s",
buffer);
}
OS::SNPrint((scriptChars + written), (kScriptSize - written), "}");
source = String::New(scriptChars);
script = Script::New(url, source, RawScript::kSourceTag);
EXPECT(CompilerTest::TestCompileScript(lib, script));
clsA = lib.LookupClass(String::Handle(Symbols::New("A")));
EXPECT(!clsA.IsNull());
ClassFinalizer::FinalizePendingClasses();
for (int i = 0; i < kNumFunctions; i++) {
OS::SNPrint(buffer, 256, "foo%d", i);
function_name = String::New(buffer);
function = clsA.LookupStaticFunction(function_name);
EXPECT(!function.IsNull());
EXPECT(CompilerTest::TestCompileFunction(function));
EXPECT(function.HasCode());
}
// Now load up class B with 1024 functions.
written = OS::SNPrint(scriptChars, kScriptSize, "class B {");
// Create one large function.
OS::SNPrint(buffer, sizeof(buffer), "static moo0([var i=1]) { ");
written += OS::SNPrint((scriptChars + written),
(kScriptSize - written),
"%s",
buffer);
// Generate a large function so that the code for this function when
// compiled will reside in a large page.
for (int i = 0; i < kLoopCount; i++) {
OS::SNPrint(buffer, sizeof(buffer), "i = i+i;");
written += OS::SNPrint((scriptChars + written),
(kScriptSize - written),
"%s",
buffer);
}
OS::SNPrint(buffer, sizeof(buffer), "return i; }");
written += OS::SNPrint((scriptChars + written),
(kScriptSize - written),
"%s",
buffer);
for (int i = 1; i < kNumFunctions; i++) {
OS::SNPrint(buffer,
256,
"static moo%d([int i=1,int j=2,int k=3]){return i+j+k;}", i);
written += OS::SNPrint((scriptChars + written),
(kScriptSize - written),
"%s",
buffer);
}
OS::SNPrint((scriptChars + written), (kScriptSize - written), "}");
url = String::New("dart-test:FindCodeObject");
source = String::New(scriptChars);
script = Script::New(url, source, RawScript::kSourceTag);
EXPECT(CompilerTest::TestCompileScript(lib, script));
clsB = lib.LookupClass(String::Handle(Symbols::New("B")));
EXPECT(!clsB.IsNull());
ClassFinalizer::FinalizePendingClasses();
for (int i = 0; i < kNumFunctions; i++) {
OS::SNPrint(buffer, 256, "moo%d", i);
function_name = String::New(buffer);
function = clsB.LookupStaticFunction(function_name);
EXPECT(!function.IsNull());
EXPECT(CompilerTest::TestCompileFunction(function));
EXPECT(function.HasCode());
}
// Now try and access these functions using the code index table.
Code& code = Code::Handle();
uword pc;
OS::SNPrint(buffer, 256, "foo%d", 123);
function_name = String::New(buffer);
function = clsA.LookupStaticFunction(function_name);
EXPECT(!function.IsNull());
code = function.CurrentCode();
EXPECT(code.Size() > 16);
pc = code.EntryPoint() + 16;
EXPECT(Code::LookupCode(pc) == code.raw());
OS::SNPrint(buffer, 256, "moo%d", 54);
function_name = String::New(buffer);
function = clsB.LookupStaticFunction(function_name);
EXPECT(!function.IsNull());
code = function.CurrentCode();
EXPECT(code.Size() > 16);
pc = code.EntryPoint() + 16;
EXPECT(Code::LookupCode(pc) == code.raw());
// Lookup the large function
OS::SNPrint(buffer, 256, "moo%d", 0);
function_name = String::New(buffer);
function = clsB.LookupStaticFunction(function_name);
EXPECT(!function.IsNull());
code = function.CurrentCode();
EXPECT(code.Size() > 16);
pc = code.EntryPoint() + 16;
#if defined(TARGET_ARCH_MIPS)
// MIPS can only Branch +/- 128KB
EXPECT(code.Size() > (PageSpace::kPageSize / 2));
EXPECT(Code::LookupCode(pc) == code.raw());
pc = code.EntryPoint() + (PageSpace::kPageSize / 4);
EXPECT(Code::LookupCode(pc) == code.raw());
#else
EXPECT(code.Size() > PageSpace::kPageSize);
EXPECT(Code::LookupCode(pc) == code.raw());
EXPECT(code.Size() > (1 * MB));
pc = code.EntryPoint() + (1 * MB);
EXPECT(Code::LookupCode(pc) == code.raw());
#endif // defined(TARGET_ARCH_MIPS)
}
} // namespace dart