}
+Handle<Code> CallStubCompiler::CompileArrayCodeCall(
+ Handle<Object> object,
+ Handle<JSObject> holder,
+ Handle<Cell> cell,
+ Handle<JSFunction> function,
+ Handle<String> name,
+ Code::StubType type) {
+ Label miss;
+
+ // Check that function is still array
+ const int argc = arguments().immediate();
+ GenerateNameCheck(name, &miss);
+ Register receiver = r1;
+
+ if (cell.is_null()) {
+ __ ldr(receiver, MemOperand(sp, argc * kPointerSize));
+
+ // Check that the receiver isn't a smi.
+ __ JumpIfSmi(receiver, &miss);
+
+ // Check that the maps haven't changed.
+ CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, r3, r0,
+ r4, name, &miss);
+ } else {
+ ASSERT(cell->value() == *function);
+ GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
+ &miss);
+ GenerateLoadFunctionFromCell(cell, function, &miss);
+ }
+
+ Handle<Smi> kind(Smi::FromInt(GetInitialFastElementsKind()), isolate());
+ Handle<Cell> kind_feedback_cell =
+ isolate()->factory()->NewCell(kind);
+ __ mov(r0, Operand(argc));
+ __ mov(r2, Operand(kind_feedback_cell));
+ __ mov(r1, Operand(function));
+
+ ArrayConstructorStub stub(isolate());
+ __ TailCallStub(&stub);
+
+ __ bind(&miss);
+ GenerateMissBranch();
+
+ // Return the generated code.
+ return GetCode(type, name);
+}
+
+
Handle<Code> CallStubCompiler::CompileArrayPushCall(
Handle<Object> object,
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
- Handle<String> name) {
+ Handle<String> name,
+ Code::StubType type) {
// ----------- S t a t e -------------
// -- r2 : name
// -- lr : return address
GenerateMissBranch();
// Return the generated code.
- return GetCode(function);
+ return GetCode(type, name);
}
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
- Handle<String> name) {
+ Handle<String> name,
+ Code::StubType type) {
// ----------- S t a t e -------------
// -- r2 : name
// -- lr : return address
GenerateMissBranch();
// Return the generated code.
- return GetCode(function);
+ return GetCode(type, name);
}
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
- Handle<String> name) {
+ Handle<String> name,
+ Code::StubType type) {
// ----------- S t a t e -------------
// -- r2 : function name
// -- lr : return address
GenerateMissBranch();
// Return the generated code.
- return GetCode(function);
+ return GetCode(type, name);
}
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
- Handle<String> name) {
+ Handle<String> name,
+ Code::StubType type) {
// ----------- S t a t e -------------
// -- r2 : function name
// -- lr : return address
GenerateMissBranch();
// Return the generated code.
- return GetCode(function);
+ return GetCode(type, name);
}
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
- Handle<String> name) {
+ Handle<String> name,
+ Code::StubType type) {
// ----------- S t a t e -------------
// -- r2 : function name
// -- lr : return address
GenerateMissBranch();
// Return the generated code.
- return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+ return GetCode(type, name);
}
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
- Handle<String> name) {
+ Handle<String> name,
+ Code::StubType type) {
// ----------- S t a t e -------------
// -- r2 : function name
// -- lr : return address
GenerateMissBranch();
// Return the generated code.
- return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+ return GetCode(type, name);
}
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
- Handle<String> name) {
+ Handle<String> name,
+ Code::StubType type) {
// ----------- S t a t e -------------
// -- r2 : function name
// -- lr : return address
GenerateMissBranch();
// Return the generated code.
- return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+ return GetCode(type, name);
}
if (HasCustomCallGenerator(function)) {
Handle<Code> code = CompileCustomCall(object, holder,
Handle<Cell>::null(),
- function, Handle<String>::cast(name));
+ function, Handle<String>::cast(name),
+ Code::CONSTANT_FUNCTION);
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
}
// -----------------------------------
if (HasCustomCallGenerator(function)) {
Handle<Code> code = CompileCustomCall(
- object, holder, cell, function, Handle<String>::cast(name));
+ object, holder, cell, function, Handle<String>::cast(name),
+ Code::NORMAL);
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
}
isolate->initial_object_prototype(),
Builtins::kArrayCode, true, true);
array_function->shared()->DontAdaptArguments();
+ array_function->shared()->set_function_data(Smi::FromInt(kArrayCode));
// This seems a bit hackish, but we need to make sure Array.length
// is 1.
graph()->MarkRecursive();
}
- call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(),
+ if (CallStubCompiler::HasCustomCallGenerator(expr->target())) {
+ // When the target has a custom call IC generator, use the IC,
+ // because it is likely to generate better code.
+ HValue* context = environment()->LookupContext();
+ call = PreProcessCall(
+ new(zone()) HCallNamed(context, var->name(), argument_count));
+ } else {
+ call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(),
argument_count));
+ }
} else {
HValue* context = environment()->LookupContext();
HGlobalObject* receiver = new(zone()) HGlobalObject(context);
}
+Handle<Code> CallStubCompiler::CompileArrayCodeCall(
+ Handle<Object> object,
+ Handle<JSObject> holder,
+ Handle<Cell> cell,
+ Handle<JSFunction> function,
+ Handle<String> name,
+ Code::StubType type) {
+ Label miss;
+
+ // Check that function is still array
+ const int argc = arguments().immediate();
+ GenerateNameCheck(name, &miss);
+
+ if (cell.is_null()) {
+ // Get the receiver from the stack.
+ __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
+
+ // Check that the receiver isn't a smi.
+ __ JumpIfSmi(edx, &miss);
+ CheckPrototypes(Handle<JSObject>::cast(object), edx, holder, ebx, eax, edi,
+ name, &miss);
+ } else {
+ ASSERT(cell->value() == *function);
+ GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
+ &miss);
+ GenerateLoadFunctionFromCell(cell, function, &miss);
+ }
+
+ Handle<Smi> kind(Smi::FromInt(GetInitialFastElementsKind()), isolate());
+ Handle<Cell> kind_feedback_cell =
+ isolate()->factory()->NewCell(kind);
+ __ mov(eax, Immediate(argc));
+ __ mov(ebx, kind_feedback_cell);
+ __ mov(edi, function);
+
+ ArrayConstructorStub stub(isolate());
+ __ TailCallStub(&stub);
+
+ __ bind(&miss);
+ GenerateMissBranch();
+
+ // Return the generated code.
+ return GetCode(type, name);
+}
+
+
Handle<Code> CallStubCompiler::CompileArrayPushCall(
Handle<Object> object,
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
- Handle<String> name) {
+ Handle<String> name,
+ Code::StubType type) {
// ----------- S t a t e -------------
// -- ecx : name
// -- esp[0] : return address
GenerateMissBranch();
// Return the generated code.
- return GetCode(function);
+ return GetCode(type, name);
}
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
- Handle<String> name) {
+ Handle<String> name,
+ Code::StubType type) {
// ----------- S t a t e -------------
// -- ecx : name
// -- esp[0] : return address
GenerateMissBranch();
// Return the generated code.
- return GetCode(function);
+ return GetCode(type, name);
}
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
- Handle<String> name) {
+ Handle<String> name,
+ Code::StubType type) {
// ----------- S t a t e -------------
// -- ecx : function name
// -- esp[0] : return address
GenerateMissBranch();
// Return the generated code.
- return GetCode(function);
+ return GetCode(type, name);
}
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
- Handle<String> name) {
+ Handle<String> name,
+ Code::StubType type) {
// ----------- S t a t e -------------
// -- ecx : function name
// -- esp[0] : return address
GenerateMissBranch();
// Return the generated code.
- return GetCode(function);
+ return GetCode(type, name);
}
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
- Handle<String> name) {
+ Handle<String> name,
+ Code::StubType type) {
// ----------- S t a t e -------------
// -- ecx : function name
// -- esp[0] : return address
GenerateMissBranch();
// Return the generated code.
- return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+ return GetCode(type, name);
}
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
- Handle<String> name) {
+ Handle<String> name,
+ Code::StubType type) {
// ----------- S t a t e -------------
// -- ecx : name
// -- esp[0] : return address
GenerateMissBranch();
// Return the generated code.
- return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+ return GetCode(type, name);
}
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
- Handle<String> name) {
+ Handle<String> name,
+ Code::StubType type) {
// ----------- S t a t e -------------
// -- ecx : name
// -- esp[0] : return address
GenerateMissBranch();
// Return the generated code.
- return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+ return GetCode(type, name);
}
if (HasCustomCallGenerator(function)) {
Handle<Code> code = CompileCustomCall(object, holder,
Handle<Cell>::null(),
- function, Handle<String>::cast(name));
+ function, Handle<String>::cast(name),
+ Code::CONSTANT_FUNCTION);
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
}
if (HasCustomCallGenerator(function)) {
Handle<Code> code = CompileCustomCall(
- object, holder, cell, function, Handle<String>::cast(name));
+ object, holder, cell, function, Handle<String>::cast(name),
+ Code::NORMAL);
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
}
V(Math, min, MathMin) \
V(Math, imul, MathImul)
-
enum BuiltinFunctionId {
+ kArrayCode,
#define DECLARE_FUNCTION_ID(ignored1, ignore2, name) \
k##name,
FUNCTIONS_WITH_ID_LIST(DECLARE_FUNCTION_ID)
PROFILE(isolate_,
CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
- JSObject::UpdateMapCodeCache(stub_holder, name, code);
+
+ if (CallStubCompiler::CanBeCached(function)) {
+ JSObject::UpdateMapCodeCache(stub_holder, name, code);
+ }
return code;
}
PROFILE(isolate(),
CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name));
GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code));
- JSObject::UpdateMapCodeCache(stub_holder, name, code);
+ if (CallStubCompiler::CanBeCached(function)) {
+ JSObject::UpdateMapCodeCache(stub_holder, name, code);
+ }
return code;
}
}
+bool CallStubCompiler::CanBeCached(Handle<JSFunction> function) {
+ if (function->shared()->HasBuiltinFunctionId()) {
+ BuiltinFunctionId id = function->shared()->builtin_function_id();
+#define CALL_GENERATOR_CASE(name) if (id == k##name) return false;
+ SITE_SPECIFIC_CALL_GENERATORS(CALL_GENERATOR_CASE)
+#undef CALL_GENERATOR_CASE
+ }
+
+ return true;
+}
+
+
Handle<Code> CallStubCompiler::CompileCustomCall(
Handle<Object> object,
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
- Handle<String> fname) {
+ Handle<String> fname,
+ Code::StubType type) {
ASSERT(HasCustomCallGenerator(function));
if (function->shared()->HasBuiltinFunctionId()) {
holder, \
cell, \
function, \
- fname); \
+ fname, \
+ type); \
}
CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE)
#undef CALL_GENERATOR_CASE
V(StringCharAt) \
V(StringFromCharCode) \
V(MathFloor) \
- V(MathAbs)
+ V(MathAbs) \
+ V(ArrayCode)
+
+
+#define SITE_SPECIFIC_CALL_GENERATORS(V) \
+ V(ArrayCode)
class CallOptimization;
Handle<Name> name);
static bool HasCustomCallGenerator(Handle<JSFunction> function);
+ static bool CanBeCached(Handle<JSFunction> function);
private:
// Compiles a custom call constant/global IC. For constant calls cell is
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
- Handle<String> name);
+ Handle<String> name,
+ Code::StubType type);
#define DECLARE_CALL_GENERATOR(name) \
Handle<Code> Compile##name##Call(Handle<Object> object, \
Handle<JSObject> holder, \
Handle<Cell> cell, \
Handle<JSFunction> function, \
- Handle<String> fname);
+ Handle<String> fname, \
+ Code::StubType type);
CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
#undef DECLARE_CALL_GENERATOR
}
+Handle<Code> CallStubCompiler::CompileArrayCodeCall(
+ Handle<Object> object,
+ Handle<JSObject> holder,
+ Handle<Cell> cell,
+ Handle<JSFunction> function,
+ Handle<String> name,
+ Code::StubType type) {
+ Label miss;
+
+ // Check that function is still array
+ const int argc = arguments().immediate();
+ GenerateNameCheck(name, &miss);
+
+ if (cell.is_null()) {
+ // Get the receiver from the stack.
+ __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
+
+ // Check that the receiver isn't a smi.
+ __ JumpIfSmi(rdx, &miss);
+ CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi,
+ name, &miss);
+ } else {
+ ASSERT(cell->value() == *function);
+ GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
+ &miss);
+ GenerateLoadFunctionFromCell(cell, function, &miss);
+ }
+
+ Handle<Smi> kind(Smi::FromInt(GetInitialFastElementsKind()), isolate());
+ Handle<Cell> kind_feedback_cell =
+ isolate()->factory()->NewCell(kind);
+ __ movq(rax, Immediate(argc));
+ __ Move(rbx, kind_feedback_cell);
+ __ Move(rdi, function);
+
+ ArrayConstructorStub stub(isolate());
+ __ TailCallStub(&stub);
+
+ __ bind(&miss);
+ GenerateMissBranch();
+
+ // Return the generated code.
+ return GetCode(type, name);
+}
+
+
Handle<Code> CallStubCompiler::CompileArrayPushCall(
Handle<Object> object,
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
- Handle<String> name) {
+ Handle<String> name,
+ Code::StubType type) {
// ----------- S t a t e -------------
// -- rcx : name
// -- rsp[0] : return address
GenerateMissBranch();
// Return the generated code.
- return GetCode(function);
+ return GetCode(type, name);
}
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
- Handle<String> name) {
+ Handle<String> name,
+ Code::StubType type) {
// ----------- S t a t e -------------
// -- rcx : name
// -- rsp[0] : return address
GenerateMissBranch();
// Return the generated code.
- return GetCode(function);
+ return GetCode(type, name);
}
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
- Handle<String> name) {
+ Handle<String> name,
+ Code::StubType type) {
// ----------- S t a t e -------------
// -- rcx : function name
// -- rsp[0] : return address
GenerateMissBranch();
// Return the generated code.
- return GetCode(function);
+ return GetCode(type, name);
}
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
- Handle<String> name) {
+ Handle<String> name,
+ Code::StubType type) {
// ----------- S t a t e -------------
// -- rcx : function name
// -- rsp[0] : return address
GenerateMissBranch();
// Return the generated code.
- return GetCode(function);
+ return GetCode(type, name);
}
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
- Handle<String> name) {
+ Handle<String> name,
+ Code::StubType type) {
// ----------- S t a t e -------------
// -- rcx : function name
// -- rsp[0] : return address
GenerateMissBranch();
// Return the generated code.
- return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+ return GetCode(type, name);
}
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
- Handle<String> name) {
+ Handle<String> name,
+ Code::StubType type) {
// TODO(872): implement this.
return Handle<Code>::null();
}
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
- Handle<String> name) {
+ Handle<String> name,
+ Code::StubType type) {
// ----------- S t a t e -------------
// -- rcx : function name
// -- rsp[0] : return address
GenerateMissBranch();
// Return the generated code.
- return cell.is_null() ? GetCode(function) : GetCode(Code::NORMAL, name);
+ return GetCode(type, name);
}
if (HasCustomCallGenerator(function)) {
Handle<Code> code = CompileCustomCall(object, holder,
Handle<PropertyCell>::null(),
- function, Handle<String>::cast(name));
+ function, Handle<String>::cast(name),
+ Code::CONSTANT_FUNCTION);
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
}
if (HasCustomCallGenerator(function)) {
Handle<Code> code = CompileCustomCall(
- object, holder, cell, function, Handle<String>::cast(name));
+ object, holder, cell, function, Handle<String>::cast(name),
+ Code::NORMAL);
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
}
--- /dev/null
+// Copyright 2012 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax --smi-only-arrays --expose-gc
+// Flags: --track-allocation-sites --noalways-opt
+
+// Test element kind of objects.
+// Since --smi-only-arrays affects builtins, its default setting at compile
+// time sticks if built with snapshot. If --smi-only-arrays is deactivated
+// by default, only a no-snapshot build actually has smi-only arrays enabled
+// in this test case. Depending on whether smi-only arrays are actually
+// enabled, this test takes the appropriate code path to check smi-only arrays.
+
+// support_smi_only_arrays = %HasFastSmiElements(new Array(1,2,3,4,5,6,7,8));
+support_smi_only_arrays = true;
+optimize_constructed_arrays = true;
+
+if (support_smi_only_arrays) {
+ print("Tests include smi-only arrays.");
+} else {
+ print("Tests do NOT include smi-only arrays.");
+}
+
+if (optimize_constructed_arrays) {
+ print("Tests include constructed array optimizations.");
+} else {
+ print("Tests do NOT include constructed array optimizations.");
+}
+
+var elements_kind = {
+ fast_smi_only : 'fast smi only elements',
+ fast : 'fast elements',
+ fast_double : 'fast double elements',
+ dictionary : 'dictionary elements',
+ external_byte : 'external byte elements',
+ external_unsigned_byte : 'external unsigned byte elements',
+ external_short : 'external short elements',
+ external_unsigned_short : 'external unsigned short elements',
+ external_int : 'external int elements',
+ external_unsigned_int : 'external unsigned int elements',
+ external_float : 'external float elements',
+ external_double : 'external double elements',
+ external_pixel : 'external pixel elements'
+}
+
+function getKind(obj) {
+ if (%HasFastSmiElements(obj)) return elements_kind.fast_smi_only;
+ if (%HasFastObjectElements(obj)) return elements_kind.fast;
+ if (%HasFastDoubleElements(obj)) return elements_kind.fast_double;
+ if (%HasDictionaryElements(obj)) return elements_kind.dictionary;
+}
+
+function isHoley(obj) {
+ if (%HasFastHoleyElements(obj)) return true;
+ return false;
+}
+
+function assertKind(expected, obj, name_opt) {
+ if (!support_smi_only_arrays &&
+ expected == elements_kind.fast_smi_only) {
+ expected = elements_kind.fast;
+ }
+ assertEquals(expected, getKind(obj), name_opt);
+}
+
+if (support_smi_only_arrays && optimize_constructed_arrays) {
+
+ // Verify that basic elements kind feedback works for non-constructor
+ // array calls (as long as the call is made through an IC, and not
+ // a CallStub).
+ (function (){
+ function create0() {
+ return Array();
+ }
+
+ // Calls through ICs need warm up through uninitialized, then
+ // premonomorphic first.
+ create0();
+ create0();
+ a = create0();
+ assertKind(elements_kind.fast_smi_only, a);
+ a[0] = 3.5;
+ b = create0();
+ assertKind(elements_kind.fast_double, b);
+
+ function create1(arg) {
+ return Array(arg);
+ }
+
+ create1(0);
+ create1(0);
+ a = create1(0);
+ assertFalse(isHoley(a));
+ assertKind(elements_kind.fast_smi_only, a);
+ a[0] = "hello";
+ b = create1(10);
+ assertTrue(isHoley(b));
+ assertKind(elements_kind.fast, b);
+
+ a = create1(100000);
+ assertKind(elements_kind.dictionary, a);
+
+ function create3(arg1, arg2, arg3) {
+ return Array(arg1, arg2, arg3);
+ }
+
+ create3();
+ create3();
+ a = create3(1,2,3);
+ a[0] = 3.5;
+ b = create3(1,2,3);
+ assertKind(elements_kind.fast_double, b);
+ assertFalse(isHoley(b));
+ })();
+
+
+ // Verify that keyed calls work
+ (function (){
+ function create0(name) {
+ return this[name]();
+ }
+
+ name = "Array";
+ create0(name);
+ create0(name);
+ a = create0(name);
+ a[0] = 3.5;
+ b = create0(name);
+ assertKind(elements_kind.fast_double, b);
+ })();
+
+
+ // Verify that the IC can't be spoofed by patching
+ (function (){
+ function create0() {
+ return Array();
+ }
+
+ create0();
+ create0();
+ a = create0();
+ assertKind(elements_kind.fast_smi_only, a);
+ var oldArray = this.Array;
+ this.Array = function() { return ["hi"]; };
+ b = create0();
+ assertEquals(["hi"], b);
+ this.Array = oldArray;
+ })();
+
+ // Verify that calls are still made through an IC after crankshaft,
+ // though the type information is reset.
+ // TODO(mvstanton): instead, consume the type feedback gathered up
+ // until crankshaft time.
+ (function (){
+ function create0() {
+ return Array();
+ }
+
+ create0();
+ create0();
+ a = create0();
+ a[0] = 3.5;
+ %OptimizeFunctionOnNextCall(create0);
+ create0();
+ create0();
+ b = create0();
+ assertKind(elements_kind.fast_smi_only, b);
+ b[0] = 3.5;
+ c = create0();
+ assertKind(elements_kind.fast_double, c);
+ assertTrue(2 != %GetOptimizationStatus(create0));
+ })();
+
+
+ // Verify that cross context calls work
+ (function (){
+ var realmA = Realm.current();
+ var realmB = Realm.create();
+ assertEquals(0, realmA);
+ assertEquals(1, realmB);
+
+ function instanceof_check(type) {
+ assertTrue(type() instanceof type);
+ assertTrue(type(5) instanceof type);
+ assertTrue(type(1,2,3) instanceof type);
+ }
+
+ var realmBArray = Realm.eval(realmB, "Array");
+ instanceof_check(Array);
+ instanceof_check(Array);
+ instanceof_check(Array);
+ instanceof_check(realmBArray);
+ instanceof_check(realmBArray);
+ instanceof_check(realmBArray);
+ })();
+}