1fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org// Copyright 2012 the V8 project authors. All rights reserved. 25c838251403b0be9a882540f1922577abba4c872ager@chromium.org// Redistribution and use in source and binary forms, with or without 35c838251403b0be9a882540f1922577abba4c872ager@chromium.org// modification, are permitted provided that the following conditions are 45c838251403b0be9a882540f1922577abba4c872ager@chromium.org// met: 55c838251403b0be9a882540f1922577abba4c872ager@chromium.org// 65c838251403b0be9a882540f1922577abba4c872ager@chromium.org// * Redistributions of source code must retain the above copyright 75c838251403b0be9a882540f1922577abba4c872ager@chromium.org// notice, this list of conditions and the following disclaimer. 85c838251403b0be9a882540f1922577abba4c872ager@chromium.org// * Redistributions in binary form must reproduce the above 95c838251403b0be9a882540f1922577abba4c872ager@chromium.org// copyright notice, this list of conditions and the following 105c838251403b0be9a882540f1922577abba4c872ager@chromium.org// disclaimer in the documentation and/or other materials provided 115c838251403b0be9a882540f1922577abba4c872ager@chromium.org// with the distribution. 125c838251403b0be9a882540f1922577abba4c872ager@chromium.org// * Neither the name of Google Inc. nor the names of its 135c838251403b0be9a882540f1922577abba4c872ager@chromium.org// contributors may be used to endorse or promote products derived 145c838251403b0be9a882540f1922577abba4c872ager@chromium.org// from this software without specific prior written permission. 155c838251403b0be9a882540f1922577abba4c872ager@chromium.org// 165c838251403b0be9a882540f1922577abba4c872ager@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 175c838251403b0be9a882540f1922577abba4c872ager@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 185c838251403b0be9a882540f1922577abba4c872ager@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 195c838251403b0be9a882540f1922577abba4c872ager@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 205c838251403b0be9a882540f1922577abba4c872ager@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 215c838251403b0be9a882540f1922577abba4c872ager@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 225c838251403b0be9a882540f1922577abba4c872ager@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 235c838251403b0be9a882540f1922577abba4c872ager@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 245c838251403b0be9a882540f1922577abba4c872ager@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 255c838251403b0be9a882540f1922577abba4c872ager@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 265c838251403b0be9a882540f1922577abba4c872ager@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 275c838251403b0be9a882540f1922577abba4c872ager@chromium.org 285c838251403b0be9a882540f1922577abba4c872ager@chromium.org 295c838251403b0be9a882540f1922577abba4c872ager@chromium.org 305c838251403b0be9a882540f1922577abba4c872ager@chromium.org#include "v8.h" 315c838251403b0be9a882540f1922577abba4c872ager@chromium.org 3293a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_TARGET_ARCH_MIPS 339dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com 3483a4728861129dc263ded92157f3e6389f851f19karlklose@chromium.org#include "codegen.h" 355c838251403b0be9a882540f1922577abba4c872ager@chromium.org#include "debug.h" 367516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org#include "deoptimizer.h" 377516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org#include "full-codegen.h" 385c838251403b0be9a882540f1922577abba4c872ager@chromium.org#include "runtime.h" 395c838251403b0be9a882540f1922577abba4c872ager@chromium.org 405c838251403b0be9a882540f1922577abba4c872ager@chromium.orgnamespace v8 { 415c838251403b0be9a882540f1922577abba4c872ager@chromium.orgnamespace internal { 425c838251403b0be9a882540f1922577abba4c872ager@chromium.org 435c838251403b0be9a882540f1922577abba4c872ager@chromium.org 445c838251403b0be9a882540f1922577abba4c872ager@chromium.org#define __ ACCESS_MASM(masm) 455c838251403b0be9a882540f1922577abba4c872ager@chromium.org 465c838251403b0be9a882540f1922577abba4c872ager@chromium.org 475c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Builtins::Generate_Adaptor(MacroAssembler* masm, 485c838251403b0be9a882540f1922577abba4c872ager@chromium.org CFunctionId id, 495c838251403b0be9a882540f1922577abba4c872ager@chromium.org BuiltinExtraArguments extra_args) { 507304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // ----------- S t a t e ------------- 517304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- a0 : number of arguments excluding receiver 527304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- a1 : called function (only guaranteed when 537304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- extra_args requires it) 547304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- cp : context 557304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- sp[0] : last argument 567304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- ... 577304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- sp[4 * (argc - 1)] : first argument 587304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- sp[4 * agrc] : receiver 597304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // ----------------------------------- 607304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 617304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Insert extra arguments. 627304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org int num_extra_args = 0; 637304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org if (extra_args == NEEDS_CALLED_FUNCTION) { 647304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org num_extra_args = 1; 657304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ push(a1); 667304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org } else { 677304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org ASSERT(extra_args == NO_EXTRA_ARGUMENTS); 687304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org } 697304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 706ff651481ed0a881f176f6d55e26679ca359792bulan@chromium.org // JumpToExternalReference expects s0 to contain the number of arguments 717304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // including the receiver and the extra arguments. 726ff651481ed0a881f176f6d55e26679ca359792bulan@chromium.org __ Addu(s0, a0, num_extra_args + 1); 736ff651481ed0a881f176f6d55e26679ca359792bulan@chromium.org __ sll(s1, s0, kPointerSizeLog2); 746ff651481ed0a881f176f6d55e26679ca359792bulan@chromium.org __ Subu(s1, s1, kPointerSize); 757304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ JumpToExternalReference(ExternalReference(id, masm->isolate())); 767304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org} 777304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 787304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 79fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org// Load the built-in InternalArray function from the current context. 80fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.orgstatic void GenerateLoadInternalArrayFunction(MacroAssembler* masm, 81fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org Register result) { 8246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org // Load the native context. 83fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org 84fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org __ lw(result, 8546839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 8646839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org __ lw(result, 8746839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org FieldMemOperand(result, GlobalObject::kNativeContextOffset)); 8846839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org // Load the InternalArray function from the native context. 89fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org __ lw(result, 90fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org MemOperand(result, 91fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org Context::SlotOffset( 92fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org Context::INTERNAL_ARRAY_FUNCTION_INDEX))); 93fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org} 94fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org 95fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org 967304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org// Load the built-in Array function from the current context. 977304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgstatic void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) { 9846839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org // Load the native context. 997304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 1007304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ lw(result, 10146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 10246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org __ lw(result, 10346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org FieldMemOperand(result, GlobalObject::kNativeContextOffset)); 10446839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org // Load the Array function from the native context. 1057304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ lw(result, 106fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org MemOperand(result, 107fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); 1087304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org} 1097304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 1107304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 111fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.orgvoid Builtins::Generate_InternalArrayCode(MacroAssembler* masm) { 112fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org // ----------- S t a t e ------------- 113fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org // -- a0 : number of arguments 114fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org // -- ra : return address 115fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org // -- sp[...]: constructor arguments 116fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org // ----------------------------------- 117fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org Label generic_array_code, one_or_more_arguments, two_or_more_arguments; 118fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org 119fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org // Get the InternalArray function. 120fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org GenerateLoadInternalArrayFunction(masm, a1); 121fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org 122fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org if (FLAG_debug_code) { 123fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org // Initial map for the builtin InternalArray functions should be maps. 124fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org __ lw(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset)); 1257ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org __ SmiTst(a2, t0); 126594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(ne, kUnexpectedInitialMapForInternalArrayFunction, 127fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org t0, Operand(zero_reg)); 128fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org __ GetObjectType(a2, a3, t0); 129594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(eq, kUnexpectedInitialMapForInternalArrayFunction, 130fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org t0, Operand(MAP_TYPE)); 131fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org } 132fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org 133fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org // Run the native code for the InternalArray function called as a normal 134fab1498f2f42726c7de46c3ed560d56dd072a8b3rossberg@chromium.org // function. 1351510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org // Tail call a stub. 1361510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org InternalArrayConstructorStub stub(masm->isolate()); 1371510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ TailCallStub(&stub); 1385c838251403b0be9a882540f1922577abba4c872ager@chromium.org} 1395c838251403b0be9a882540f1922577abba4c872ager@chromium.org 1405c838251403b0be9a882540f1922577abba4c872ager@chromium.org 1415c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Builtins::Generate_ArrayCode(MacroAssembler* masm) { 1427304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // ----------- S t a t e ------------- 1437304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- a0 : number of arguments 1447304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- ra : return address 1457304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- sp[...]: constructor arguments 1467304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // ----------------------------------- 1477304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org Label generic_array_code; 1487304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 1497304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Get the Array function. 1507304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org GenerateLoadArrayFunction(masm, a1); 1517304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 1527304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org if (FLAG_debug_code) { 1537304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Initial map for the builtin Array functions should be maps. 1547304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ lw(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset)); 1557ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org __ SmiTst(a2, t0); 156594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(ne, kUnexpectedInitialMapForArrayFunction1, 1577304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org t0, Operand(zero_reg)); 1587304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ GetObjectType(a2, a3, t0); 159594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(eq, kUnexpectedInitialMapForArrayFunction2, 1607304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org t0, Operand(MAP_TYPE)); 1617304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org } 1627304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 1637304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Run the native code for the Array function called as a normal function. 1641510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org // Tail call a stub. 1651510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org Handle<Object> undefined_sentinel( 1661510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org masm->isolate()->heap()->undefined_value(), 1671510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org masm->isolate()); 1681510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ li(a2, Operand(undefined_sentinel)); 1691510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org ArrayConstructorStub stub(masm->isolate()); 1701510d58cbcf57c82a10e7d390bfe21a7ae68ba43mstarzinger@chromium.org __ TailCallStub(&stub); 1715c838251403b0be9a882540f1922577abba4c872ager@chromium.org} 1725c838251403b0be9a882540f1922577abba4c872ager@chromium.org 1735c838251403b0be9a882540f1922577abba4c872ager@chromium.org 1747516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Builtins::Generate_StringConstructCode(MacroAssembler* masm) { 1757304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // ----------- S t a t e ------------- 1767304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- a0 : number of arguments 1777304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- a1 : constructor function 1787304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- ra : return address 1797304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- sp[(argc - n - 1) * 4] : arg[n] (zero based) 1807304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- sp[argc * 4] : receiver 1817304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // ----------------------------------- 1827304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org Counters* counters = masm->isolate()->counters(); 1837304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ IncrementCounter(counters->string_ctor_calls(), 1, a2, a3); 1847304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 1857304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org Register function = a1; 1867304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org if (FLAG_debug_code) { 1877304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, a2); 188594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(eq, kUnexpectedStringFunction, function, Operand(a2)); 1897304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org } 1907304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 1917304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Load the first arguments in a0 and get rid of the rest. 1927304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org Label no_arguments; 1937304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Branch(&no_arguments, eq, a0, Operand(zero_reg)); 1947304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // First args = sp[(argc - 1) * 4]. 1957304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Subu(a0, a0, Operand(1)); 1967304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ sll(a0, a0, kPointerSizeLog2); 1977304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Addu(sp, a0, sp); 1987304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ lw(a0, MemOperand(sp)); 1997304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // sp now point to args[0], drop args[0] + receiver. 2007304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Drop(2); 2017304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 2027304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org Register argument = a2; 2037304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org Label not_cached, argument_is_string; 204528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org __ LookupNumberStringCache(a0, // Input. 205528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org argument, // Result. 206528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org a3, // Scratch. 207528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org t0, // Scratch. 208528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org t1, // Scratch. 209528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org ¬_cached); 2107304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ IncrementCounter(counters->string_ctor_cached_number(), 1, a3, t0); 2117304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ bind(&argument_is_string); 2127304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 2137304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // ----------- S t a t e ------------- 2147304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- a2 : argument converted to string 2157304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- a1 : constructor function 2167304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- ra : return address 2177304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // ----------------------------------- 2187304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 2197304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org Label gc_required; 2204c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org __ Allocate(JSValue::kSize, 2214c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org v0, // Result. 2224c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org a3, // Scratch. 2234c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org t0, // Scratch. 2244c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org &gc_required, 2254c54a2aa3c7806f38af0c7dfde22395232ebdff7jkummerow@chromium.org TAG_OBJECT); 2267304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 2277304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Initialising the String Object. 2287304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org Register map = a3; 2297304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ LoadGlobalFunctionInitialMap(function, map, t0); 2307304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org if (FLAG_debug_code) { 2317304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ lbu(t0, FieldMemOperand(map, Map::kInstanceSizeOffset)); 232594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(eq, kUnexpectedStringWrapperInstanceSize, 2337304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org t0, Operand(JSValue::kSize >> kPointerSizeLog2)); 2347304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ lbu(t0, FieldMemOperand(map, Map::kUnusedPropertyFieldsOffset)); 235594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(eq, kUnexpectedUnusedPropertiesOfStringWrapper, 2367304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org t0, Operand(zero_reg)); 2377304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org } 2387304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ sw(map, FieldMemOperand(v0, HeapObject::kMapOffset)); 2397304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 2407304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ LoadRoot(a3, Heap::kEmptyFixedArrayRootIndex); 2417304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ sw(a3, FieldMemOperand(v0, JSObject::kPropertiesOffset)); 2427304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ sw(a3, FieldMemOperand(v0, JSObject::kElementsOffset)); 2437304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 2447304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ sw(argument, FieldMemOperand(v0, JSValue::kValueOffset)); 2457304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 2467304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Ensure the object is fully initialized. 2477304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize); 2487304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 2497304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Ret(); 2507304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 2517304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // The argument was not found in the number to string cache. Check 2527304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // if it's a string already before calling the conversion builtin. 2537304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org Label convert_argument; 2547304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ bind(¬_cached); 2557304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ JumpIfSmi(a0, &convert_argument); 2567304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 2577304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Is it a String? 2587304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ lw(a2, FieldMemOperand(a0, HeapObject::kMapOffset)); 2597304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ lbu(a3, FieldMemOperand(a2, Map::kInstanceTypeOffset)); 2601805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org STATIC_ASSERT(kNotStringTag != 0); 2617304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ And(t0, a3, Operand(kIsNotStringMask)); 2627304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Branch(&convert_argument, ne, t0, Operand(zero_reg)); 2637304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ mov(argument, a0); 2647304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ IncrementCounter(counters->string_ctor_conversions(), 1, a3, t0); 2657304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Branch(&argument_is_string); 2667304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 2677304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Invoke the conversion builtin and put the result into a2. 2687304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ bind(&convert_argument); 2697304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ push(function); // Preserve the function. 2707304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ IncrementCounter(counters->string_ctor_conversions(), 1, a3, t0); 271c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { 272c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FrameScope scope(masm, StackFrame::INTERNAL); 273c1789eecd43bf9c5497636592bf14fa754d04c89machenbach@chromium.org __ push(a0); 274c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION); 275c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 2767304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ pop(function); 2777304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ mov(argument, v0); 2787304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Branch(&argument_is_string); 2797304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 2807304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Load the empty string into a2, remove the receiver from the 2817304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // stack, and jump back to the case where the argument is a string. 2827304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ bind(&no_arguments); 283750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org __ LoadRoot(argument, Heap::kempty_stringRootIndex); 2847304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Drop(1); 2857304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Branch(&argument_is_string); 2867304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 2877304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // At this point the argument is already a string. Call runtime to 2887304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // create a string wrapper. 2897304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ bind(&gc_required); 2907304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ IncrementCounter(counters->string_ctor_gc_required(), 1, a3, t0); 291c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { 292c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FrameScope scope(masm, StackFrame::INTERNAL); 293c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(argument); 294c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CallRuntime(Runtime::kNewStringWrapper, 1); 295c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 2967304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Ret(); 2977516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org} 2987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 2997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 3004a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.orgstatic void CallRuntimePassFunction(MacroAssembler* masm, 3014a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org Runtime::FunctionId function_id) { 3024a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 3034a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org // Push a copy of the function onto the stack. 304057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org // Push call kind information and function as parameter to the runtime call. 305057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org __ Push(a1, t1, a1); 3064a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org 3074a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org __ CallRuntime(function_id, 1); 308057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org // Restore call kind information and receiver. 309057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org __ Pop(a1, t1); 3104a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org} 3114a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org 3124a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org 313129d398d682e6ca3910808c913212ce532f1e155danno@chromium.orgstatic void GenerateTailCallToSharedCode(MacroAssembler* masm) { 314129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); 315129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org __ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kCodeOffset)); 316129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org __ Addu(at, a2, Operand(Code::kHeaderSize - kHeapObjectTag)); 317129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org __ Jump(at); 318129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org} 319129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org 320129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org 321129d398d682e6ca3910808c913212ce532f1e155danno@chromium.orgvoid Builtins::Generate_InRecompileQueue(MacroAssembler* masm) { 3224a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org // Checking whether the queued function is ready for install is optional, 3234a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org // since we come across interrupts and stack checks elsewhere. However, 3244a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org // not checking may delay installing ready functions, and always checking 3254a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org // would be quite expensive. A good compromise is to first check against 3264a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org // stack limit as a cue for an interrupt signal. 3274a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org Label ok; 3284a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org __ LoadRoot(t0, Heap::kStackLimitRootIndex); 3294a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org __ Branch(&ok, hs, sp, Operand(t0)); 3304a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org 3314a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org CallRuntimePassFunction(masm, Runtime::kTryInstallRecompiledCode); 3324a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org // Tail call to returned code. 3334a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org __ Addu(at, v0, Operand(Code::kHeaderSize - kHeapObjectTag)); 3344a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org __ Jump(at); 3356e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org 3364a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org __ bind(&ok); 3374a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org GenerateTailCallToSharedCode(masm); 3386e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org} 3396e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org 3406e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org 3419259716434187c932704601f700375e53d865de8rossberg@chromium.orgvoid Builtins::Generate_ConcurrentRecompile(MacroAssembler* masm) { 3424a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org CallRuntimePassFunction(masm, Runtime::kConcurrentRecompile); 343129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org GenerateTailCallToSharedCode(masm); 344129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org} 345129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org 346129d398d682e6ca3910808c913212ce532f1e155danno@chromium.org 347fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.orgstatic void Generate_JSConstructStubHelper(MacroAssembler* masm, 348fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org bool is_api_function, 349fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org bool count_constructions) { 3507304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // ----------- S t a t e ------------- 3517304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- a0 : number of arguments 3527304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- a1 : constructor function 3537304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- ra : return address 3547304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- sp[...]: constructor arguments 3557304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // ----------------------------------- 3567304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 3577304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Should never count constructions for api objects. 3587304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org ASSERT(!is_api_function || !count_constructions); 3597304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 3607304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org Isolate* isolate = masm->isolate(); 3617304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 3627304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // ----------- S t a t e ------------- 3637304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- a0 : number of arguments 3647304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- a1 : constructor function 3657304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- ra : return address 3667304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- sp[...]: constructor arguments 3677304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // ----------------------------------- 3687304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 3697304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Enter a construct frame. 370c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { 371c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FrameScope scope(masm, StackFrame::CONSTRUCT); 3727304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 373c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Preserve the two incoming parameters on the stack. 374c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sll(a0, a0, kSmiTagSize); // Tag arguments count. 375c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ MultiPushReversed(a0.bit() | a1.bit()); 3767304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 377c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Use t7 to hold undefined, which is used in several places below. 378c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ LoadRoot(t7, Heap::kUndefinedValueRootIndex); 3797304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 380c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label rt_call, allocated; 381c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Try to allocate the object without transitioning into C code. If any of 382c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // the preconditions is not met, the code bails out to the runtime call. 383c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com if (FLAG_inline_new) { 384c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label undo_allocation; 3857304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org#ifdef ENABLE_DEBUGGER_SUPPORT 386c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ExternalReference debug_step_in_fp = 387c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ExternalReference::debug_step_in_fp_address(isolate); 388c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ li(a2, Operand(debug_step_in_fp)); 389c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(a2, MemOperand(a2)); 390c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Branch(&rt_call, ne, a2, Operand(zero_reg)); 3917304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org#endif 3927304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 393c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Load the initial map and verify that it is in fact a map. 394c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a1: constructor function 395c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset)); 396c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org __ JumpIfSmi(a2, &rt_call); 397c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ GetObjectType(a2, a3, t4); 398c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Branch(&rt_call, ne, t4, Operand(MAP_TYPE)); 399c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 400c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Check that the constructor is not constructing a JSFunction (see 401c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // comments in Runtime_NewObject in runtime.cc). In which case the 402c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // initial map's instance type would be JS_FUNCTION_TYPE. 403c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a1: constructor function 404c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a2: initial map 405c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lbu(a3, FieldMemOperand(a2, Map::kInstanceTypeOffset)); 406c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Branch(&rt_call, eq, a3, Operand(JS_FUNCTION_TYPE)); 4077304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 4087304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org if (count_constructions) { 409c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label allocate; 410c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Decrease generous allocation count. 411c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(a3, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); 412c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com MemOperand constructor_count = 413c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FieldMemOperand(a3, SharedFunctionInfo::kConstructionCountOffset); 414c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lbu(t0, constructor_count); 415c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Subu(t0, t0, Operand(1)); 416c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sb(t0, constructor_count); 417c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Branch(&allocate, ne, t0, Operand(zero_reg)); 418c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 419057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org __ Push(a1, a2, a1); // a1 = Constructor. 420c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // The call will replace the stub, so the countdown is only done once. 421c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); 422c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 423057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org __ Pop(a1, a2); 424c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 425c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&allocate); 4267304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org } 4277304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 428c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Now allocate the JSObject on the heap. 429c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a1: constructor function 430c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a2: initial map 431c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lbu(a3, FieldMemOperand(a2, Map::kInstanceSizeOffset)); 432f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org __ Allocate(a3, t4, t5, t6, &rt_call, SIZE_IN_WORDS); 433c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 434c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Allocated the JSObject, now initialize the fields. Map is set to 435c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // initial map and properties and elements are set to empty fixed array. 436c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a1: constructor function 437c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a2: initial map 438c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a3: object size 439c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // t4: JSObject (not tagged) 440c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ LoadRoot(t6, Heap::kEmptyFixedArrayRootIndex); 441c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(t5, t4); 442c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sw(a2, MemOperand(t5, JSObject::kMapOffset)); 443c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sw(t6, MemOperand(t5, JSObject::kPropertiesOffset)); 444c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sw(t6, MemOperand(t5, JSObject::kElementsOffset)); 445c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Addu(t5, t5, Operand(3*kPointerSize)); 446c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); 447c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset); 448c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset); 449c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 450c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Fill all the in-object properties with appropriate filler. 451c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a1: constructor function 452c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a2: initial map 453c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a3: object size (in words) 454c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // t4: JSObject (not tagged) 455c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // t5: First in-object property of JSObject (not tagged) 456c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sll(t0, a3, kPointerSizeLog2); 457c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ addu(t6, t4, t0); // End of object. 458c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize); 459b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org __ LoadRoot(t7, Heap::kUndefinedValueRootIndex); 460b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org if (count_constructions) { 461b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org __ lw(a0, FieldMemOperand(a2, Map::kInstanceSizesOffset)); 462b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org __ Ext(a0, a0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte, 463b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org kBitsPerByte); 464b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org __ sll(t0, a0, kPointerSizeLog2); 465b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org __ addu(a0, t5, t0); 466b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org // a0: offset of first field after pre-allocated fields 467b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org if (FLAG_debug_code) { 468594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields, 469b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org a0, Operand(t6)); 470c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 471b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org __ InitializeFieldsWithFiller(t5, a0, t7); 472b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org // To allow for truncation. 473b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org __ LoadRoot(t7, Heap::kOnePointerFillerMapRootIndex); 474c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 475b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org __ InitializeFieldsWithFiller(t5, t6, t7); 4767304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 477c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Add the object tag to make the JSObject real, so that we can continue 478c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // and jump into the continuation code at any time from now on. Any 479c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // failures need to undo the allocation, so that the heap is in a 480c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // consistent state and verifiable. 481c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Addu(t4, t4, Operand(kHeapObjectTag)); 482c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 483c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Check if a non-empty properties array is needed. Continue with 484c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // allocated object if not fall through to runtime call if it is. 485c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a1: constructor function 486c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // t4: JSObject 487c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // t5: start of next object (not tagged) 488c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lbu(a3, FieldMemOperand(a2, Map::kUnusedPropertyFieldsOffset)); 489c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // The field instance sizes contains both pre-allocated property fields 490c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // and in-object properties. 491c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(a0, FieldMemOperand(a2, Map::kInstanceSizesOffset)); 492b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org __ Ext(t6, a0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte, 493b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org kBitsPerByte); 494b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org __ Addu(a3, a3, Operand(t6)); 495b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org __ Ext(t6, a0, Map::kInObjectPropertiesByte * kBitsPerByte, 496b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org kBitsPerByte); 497b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org __ subu(a3, a3, t6); 498c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 499c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Done if no extra properties are to be allocated. 500c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Branch(&allocated, eq, a3, Operand(zero_reg)); 501594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(greater_equal, kPropertyAllocationCountFailed, 502c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com a3, Operand(zero_reg)); 503c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 504c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Scale the number of elements by pointer size and add the header for 505c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // FixedArrays to the start of the next object calculation from above. 506c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a1: constructor 507c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a3: number of elements in properties array 508c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // t4: JSObject 509c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // t5: start of next object 510c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Addu(a0, a3, Operand(FixedArray::kHeaderSize / kPointerSize)); 511f705b5034dc5bc422ac1019b591469a7d0534772mstarzinger@chromium.org __ Allocate( 512c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com a0, 513c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com t5, 514c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com t6, 515c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com a2, 516c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com &undo_allocation, 517c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS)); 518c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 519c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Initialize the FixedArray. 520c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a1: constructor 5212efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org // a3: number of elements in properties array (untagged) 522c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // t4: JSObject 523c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // t5: start of next object 524c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ LoadRoot(t6, Heap::kFixedArrayMapRootIndex); 525c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(a2, t5); 526c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sw(t6, MemOperand(a2, JSObject::kMapOffset)); 527c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sll(a0, a3, kSmiTagSize); 528c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sw(a0, MemOperand(a2, FixedArray::kLengthOffset)); 529c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Addu(a2, a2, Operand(2 * kPointerSize)); 530c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 531c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); 532c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset); 533c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 534c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Initialize the fields to undefined. 535c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a1: constructor 536c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a2: First element of FixedArray (not tagged) 537c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a3: number of elements in properties array 538c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // t4: JSObject 539c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // t5: FixedArray (not tagged) 540c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sll(t3, a3, kPointerSizeLog2); 541c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ addu(t6, a2, t3); // End of object. 542c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize); 543c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { Label loop, entry; 544c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com if (count_constructions) { 545c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ LoadRoot(t7, Heap::kUndefinedValueRootIndex); 546c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } else if (FLAG_debug_code) { 547c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ LoadRoot(t8, Heap::kUndefinedValueRootIndex); 548594006017e46d82ed7146611dc12c20e3c509c7ddanno@chromium.org __ Assert(eq, kUndefinedValueNotLoaded, t7, Operand(t8)); 549c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 550c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ jmp(&entry); 551c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&loop); 552c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sw(t7, MemOperand(a2)); 553c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ addiu(a2, a2, kPointerSize); 554c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&entry); 555c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Branch(&loop, less, a2, Operand(t6)); 5567304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org } 557c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 558c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Store the initialized FixedArray into the properties field of 559c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // the JSObject. 560c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a1: constructor function 561c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // t4: JSObject 562c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // t5: FixedArray (not tagged) 563c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Addu(t5, t5, Operand(kHeapObjectTag)); // Add the heap tag. 564c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sw(t5, FieldMemOperand(t4, JSObject::kPropertiesOffset)); 565c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 566c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Continue with JSObject being successfully allocated. 567c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a1: constructor function 568c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a4: JSObject 569c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ jmp(&allocated); 570c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 571c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Undo the setting of the new top so that the heap is verifiable. For 572c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // example, the map's unused properties potentially do not match the 573c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // allocated objects unused properties. 574c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // t4: JSObject (previous new top) 575c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&undo_allocation); 576c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ UndoAllocationInNewSpace(t4, t5); 5777304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org } 5787304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 579c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&rt_call); 580c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Allocate the new receiver object using the runtime call. 5817304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a1: constructor function 582c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(a1); // Argument for Runtime_NewObject. 583c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CallRuntime(Runtime::kNewObject, 1); 584c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(t4, v0); 5857304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 586c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Receiver for constructor call allocated. 587c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // t4: JSObject 588c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&allocated); 589c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(t4); 59078d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org __ push(t4); 5917304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 592c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Reload the number of arguments from the stack. 593c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // sp[0]: receiver 59478d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org // sp[1]: receiver 59578d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org // sp[2]: constructor function 59678d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org // sp[3]: number of arguments (smi-tagged) 59778d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org __ lw(a1, MemOperand(sp, 2 * kPointerSize)); 59878d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org __ lw(a3, MemOperand(sp, 3 * kPointerSize)); 5997304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 600f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com // Set up pointer to last argument. 601c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Addu(a2, fp, Operand(StandardFrameConstants::kCallerSPOffset)); 6027304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 603f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com // Set up number of arguments for function call below. 604c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ srl(a0, a3, kSmiTagSize); 6057304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 606c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Copy arguments and receiver to the expression stack. 607c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a0: number of arguments 608c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a1: constructor function 609c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a2: address of last argument (caller sp) 610c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a3: number of arguments (smi-tagged) 611c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // sp[0]: receiver 61278d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org // sp[1]: receiver 61378d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org // sp[2]: constructor function 61478d1ad443658709d6c27809001a0e71efd8b898fyangguo@chromium.org // sp[3]: number of arguments (smi-tagged) 615c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label loop, entry; 616c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ jmp(&entry); 617c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&loop); 618c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sll(t0, a3, kPointerSizeLog2 - kSmiTagSize); 619c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Addu(t0, a2, Operand(t0)); 620c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(t1, MemOperand(t0)); 621c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(t1); 622c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&entry); 623c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Addu(a3, a3, Operand(-2)); 624c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Branch(&loop, greater_equal, a3, Operand(zero_reg)); 6257304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 626c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Call the function. 627c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a0: number of arguments 628c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a1: constructor function 629c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com if (is_api_function) { 630c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); 631c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Handle<Code> code = 632c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com masm->isolate()->builtins()->HandleApiCallConstruct(); 633c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ParameterCount expected(0); 634c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InvokeCode(code, expected, expected, 635c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com RelocInfo::CODE_TARGET, CALL_FUNCTION, CALL_AS_METHOD); 636c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } else { 637c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ParameterCount actual(a0); 638c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InvokeFunction(a1, actual, CALL_FUNCTION, 639c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com NullCallWrapper(), CALL_AS_METHOD); 640c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 6417304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 642812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org // Store offset of return address for deoptimizer. 643812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org if (!is_api_function && !count_constructions) { 644812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); 645812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org } 646812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org 647c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Restore context from the frame. 648c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 649c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 650c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // If the result is an object (in the ECMA sense), we should get rid 651c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // of the receiver and use the result; see ECMA-262 section 13.2.2-7 652c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // on page 74. 653c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label use_receiver, exit; 654c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 655c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // If the result is a smi, it is *not* an object in the ECMA sense. 656c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // v0: result 657c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // sp[0]: receiver (newly allocated object) 658c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // sp[1]: constructor function 659c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // sp[2]: number of arguments (smi-tagged) 660c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org __ JumpIfSmi(v0, &use_receiver); 661c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 662c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // If the type of the result (stored in its map) is less than 663c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. 6649faefa4670e0c454c6e56bb87b4410d73828e84fsvenpanne@chromium.org __ GetObjectType(v0, a1, a3); 665c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Branch(&exit, greater_equal, a3, Operand(FIRST_SPEC_OBJECT_TYPE)); 666c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 667c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Throw away the result of the constructor invocation and use the 668c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // on-stack receiver as the result. 669c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&use_receiver); 670c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(v0, MemOperand(sp)); 671c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 672c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Remove receiver from the stack, remove caller arguments, and 673c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // return. 674c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&exit); 675c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // v0: result 676c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // sp[0]: receiver (newly allocated object) 677c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // sp[1]: constructor function 678c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // sp[2]: number of arguments (smi-tagged) 679c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(a1, MemOperand(sp, 2 * kPointerSize)); 680c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 681c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Leave construct frame. 6827304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org } 6837304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 6847304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ sll(t0, a1, kPointerSizeLog2 - 1); 6857304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Addu(sp, sp, t0); 6867304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Addu(sp, sp, kPointerSize); 6877304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ IncrementCounter(isolate->counters()->constructed_objects(), 1, a1, a2); 6887304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Ret(); 6895c838251403b0be9a882540f1922577abba4c872ager@chromium.org} 6905c838251403b0be9a882540f1922577abba4c872ager@chromium.org 6915c838251403b0be9a882540f1922577abba4c872ager@chromium.org 6927516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { 6937304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org Generate_JSConstructStubHelper(masm, false, true); 6945c838251403b0be9a882540f1922577abba4c872ager@chromium.org} 6955c838251403b0be9a882540f1922577abba4c872ager@chromium.org 6965c838251403b0be9a882540f1922577abba4c872ager@chromium.org 6977516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { 6987304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org Generate_JSConstructStubHelper(masm, false, false); 6995c838251403b0be9a882540f1922577abba4c872ager@chromium.org} 7005c838251403b0be9a882540f1922577abba4c872ager@chromium.org 7015c838251403b0be9a882540f1922577abba4c872ager@chromium.org 7027516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { 7037304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org Generate_JSConstructStubHelper(masm, true, false); 7047304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org} 7057304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 7067304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 7077304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgstatic void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, 7087304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org bool is_construct) { 7097304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Called from JSEntryStub::GenerateBody 7107304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 7117304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // ----------- S t a t e ------------- 7127304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- a0: code entry 7137304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- a1: function 7142efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org // -- a2: receiver_pointer 7157304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- a3: argc 7167304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- s0: argv 7177304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // ----------------------------------- 71807237aaaed914a17c1afd64234883bff619581d5palfia@homejinni.com ProfileEntryHookStub::MaybeCallEntryHook(masm); 7197304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 7207304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Clear the context before we push it when entering the JS frame. 7217304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ mov(cp, zero_reg); 7227304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 7237304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Enter an internal frame. 724c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { 725c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FrameScope scope(masm, StackFrame::INTERNAL); 7267304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 727c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Set up the context from the function argument. 728c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); 7297304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 730c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Push the function and the receiver onto the stack. 731c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Push(a1, a2); 7327304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 733c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Copy arguments to the stack in a loop. 734c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a3: argc 7352efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org // s0: argv, i.e. points to first arg 736c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label loop, entry; 737c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sll(t0, a3, kPointerSizeLog2); 738c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ addu(t2, s0, t0); 739c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ b(&entry); 740c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ nop(); // Branch delay slot nop. 741c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // t2 points past last arg. 742c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&loop); 743c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(t0, MemOperand(s0)); // Read next parameter. 744c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ addiu(s0, s0, kPointerSize); 745c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(t0, MemOperand(t0)); // Dereference handle. 746c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(t0); // Push parameter. 747c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&entry); 748c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Branch(&loop, ne, s0, Operand(t2)); 749c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 750c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Initialize all JavaScript callee-saved registers, since they will be seen 751c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // by the garbage collector as part of handlers. 752c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ LoadRoot(t0, Heap::kUndefinedValueRootIndex); 753c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(s1, t0); 754c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(s2, t0); 755c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(s3, t0); 756c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(s4, t0); 757c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(s5, t0); 758c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // s6 holds the root address. Do not clobber. 759c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // s7 is cp. Do not init. 760c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 761c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Invoke the code and pass argc as a0. 762c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(a0, a3); 763c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com if (is_construct) { 764750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org // No type feedback cell is available 765750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org Handle<Object> undefined_sentinel( 766750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org masm->isolate()->heap()->undefined_value(), masm->isolate()); 767750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org __ li(a2, Operand(undefined_sentinel)); 768fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); 769fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org __ CallStub(&stub); 770c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } else { 771c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ParameterCount actual(a0); 772c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InvokeFunction(a1, actual, CALL_FUNCTION, 773c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com NullCallWrapper(), CALL_AS_METHOD); 774c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 7757304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 776c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Leave internal frame. 777c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 7787304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 7797304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Jump(ra); 7805c838251403b0be9a882540f1922577abba4c872ager@chromium.org} 7815c838251403b0be9a882540f1922577abba4c872ager@chromium.org 7825c838251403b0be9a882540f1922577abba4c872ager@chromium.org 7835c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { 7847304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org Generate_JSEntryTrampolineHelper(masm, false); 7855c838251403b0be9a882540f1922577abba4c872ager@chromium.org} 7865c838251403b0be9a882540f1922577abba4c872ager@chromium.org 7875c838251403b0be9a882540f1922577abba4c872ager@chromium.org 7885c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { 7897304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org Generate_JSEntryTrampolineHelper(masm, true); 7907516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org} 7917516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 7927516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 7937516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Builtins::Generate_LazyCompile(MacroAssembler* masm) { 7944a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org CallRuntimePassFunction(masm, Runtime::kLazyCompile); 7957304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Do a tail-call of the compiled function. 7964a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org __ Addu(t9, v0, Operand(Code::kHeaderSize - kHeapObjectTag)); 7977304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Jump(t9); 7987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org} 7997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 8007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 8017516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Builtins::Generate_LazyRecompile(MacroAssembler* masm) { 8024a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org CallRuntimePassFunction(masm, Runtime::kLazyRecompile); 8037304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Do a tail-call of the compiled function. 8044a35c5a501e5b966f895ddea8e19c3ca232cb23fdslomov@chromium.org __ Addu(t9, v0, Operand(Code::kHeaderSize - kHeapObjectTag)); 8057304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Jump(t9); 8067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org} 8077516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 8087516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 809fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgstatic void GenerateMakeCodeYoungAgainCommon(MacroAssembler* masm) { 810fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // For now, we are relying on the fact that make_code_young doesn't do any 811fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // garbage collection which allows us to save/restore the registers without 812fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // worrying about which of them contain pointers. We also don't build an 813fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // internal frame to make the code faster, since we shouldn't have to do stack 814fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // crawls in MakeCodeYoung. This seems a bit fragile. 815fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org 816f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org // Set a0 to point to the head of the PlatformCodeAge sequence. 817fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ Subu(a0, a0, 818fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org Operand((kNoCodeAgeSequenceLength - 1) * Assembler::kInstrSize)); 819fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org 820fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // The following registers must be saved and restored when calling through to 821fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // the runtime: 822fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org // a0 - contains return address (beginning of patch sequence) 823528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org // a1 - isolate 824fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org RegList saved_regs = 825fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org (a0.bit() | a1.bit() | ra.bit() | fp.bit()) & ~sp.bit(); 826fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org FrameScope scope(masm, StackFrame::MANUAL); 827fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ MultiPush(saved_regs); 828528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org __ PrepareCallCFunction(1, 0, a2); 829528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org __ li(a1, Operand(ExternalReference::isolate_address(masm->isolate()))); 830fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ CallCFunction( 831528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org ExternalReference::get_make_code_young_function(masm->isolate()), 2); 832fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ MultiPop(saved_regs); 833fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org __ Jump(a0); 834fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org} 835fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org 836fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org#define DEFINE_CODE_AGE_BUILTIN_GENERATOR(C) \ 837fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgvoid Builtins::Generate_Make##C##CodeYoungAgainEvenMarking( \ 838fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org MacroAssembler* masm) { \ 839fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org GenerateMakeCodeYoungAgainCommon(masm); \ 840fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org} \ 841fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgvoid Builtins::Generate_Make##C##CodeYoungAgainOddMarking( \ 842fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org MacroAssembler* masm) { \ 843fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org GenerateMakeCodeYoungAgainCommon(masm); \ 844fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org} 845fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.orgCODE_AGE_LIST(DEFINE_CODE_AGE_BUILTIN_GENERATOR) 846fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org#undef DEFINE_CODE_AGE_BUILTIN_GENERATOR 847fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org 848fb37721ea34922d8758d5cb26ae465aaf241e6b6yangguo@chromium.org 849c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.orgvoid Builtins::Generate_MarkCodeAsExecutedOnce(MacroAssembler* masm) { 850c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org // For now, as in GenerateMakeCodeYoungAgainCommon, we are relying on the fact 851c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org // that make_code_young doesn't do any garbage collection which allows us to 852c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org // save/restore the registers without worrying about which of them contain 853c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org // pointers. 854c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org 855f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org // Set a0 to point to the head of the PlatformCodeAge sequence. 856c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ Subu(a0, a0, 857c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org Operand((kNoCodeAgeSequenceLength - 1) * Assembler::kInstrSize)); 858c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org 859c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org // The following registers must be saved and restored when calling through to 860c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org // the runtime: 861c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org // a0 - contains return address (beginning of patch sequence) 862c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org // a1 - isolate 863c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org RegList saved_regs = 864c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org (a0.bit() | a1.bit() | ra.bit() | fp.bit()) & ~sp.bit(); 865c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org FrameScope scope(masm, StackFrame::MANUAL); 866c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ MultiPush(saved_regs); 867c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ PrepareCallCFunction(1, 0, a2); 868c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ li(a1, Operand(ExternalReference::isolate_address(masm->isolate()))); 869c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ CallCFunction( 870c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org ExternalReference::get_mark_code_as_executed_function(masm->isolate()), 871c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org 2); 872c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ MultiPop(saved_regs); 873c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org 874c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org // Perform prologue operations usually performed by the young code stub. 875c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ Push(ra, fp, cp, a1); 8767ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org __ Addu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); 877c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org 878c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org // Jump to point after the code-age stub. 879c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ Addu(a0, a0, Operand((kNoCodeAgeSequenceLength) * Assembler::kInstrSize)); 880c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org __ Jump(a0); 881c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org} 882c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org 883c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org 884c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.orgvoid Builtins::Generate_MarkCodeAsExecutedTwice(MacroAssembler* masm) { 885c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org GenerateMakeCodeYoungAgainCommon(masm); 886c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org} 887c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org 888c9913f099d68d3604e53b19d0fc5abe309143bdcbmeurer@chromium.org 889f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgstatic void Generate_NotifyStubFailureHelper(MacroAssembler* masm, 890f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org SaveFPRegsMode save_doubles) { 89159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org { 89259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 89359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org 89459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org // Preserve registers across notification, this is important for compiled 89559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org // stubs that tail call the runtime on deopts passing their parameters in 89659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org // registers. 89759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ MultiPush(kJSCallerSaved | kCalleeSaved); 89859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org // Pass the function and deoptimization type to the runtime system. 899f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org __ CallRuntime(Runtime::kNotifyStubFailure, 0, save_doubles); 90059297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ MultiPop(kJSCallerSaved | kCalleeSaved); 90159297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org } 90259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org 90359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ Addu(sp, sp, Operand(kPointerSize)); // Ignore state 904e3b8d0fe80e858c990832db1233c069f8b8cd5c9mstarzinger@chromium.org __ Jump(ra); // Jump to miss handler 90559297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org} 90659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org 90759297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org 908f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgvoid Builtins::Generate_NotifyStubFailure(MacroAssembler* masm) { 909f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org Generate_NotifyStubFailureHelper(masm, kDontSaveFPRegs); 910f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org} 911f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 912f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 913f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.orgvoid Builtins::Generate_NotifyStubFailureSaveDoubles(MacroAssembler* masm) { 914f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org Generate_NotifyStubFailureHelper(masm, kSaveFPRegs); 915f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org} 916f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 917f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org 918c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.orgstatic void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm, 919c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org Deoptimizer::BailoutType type) { 920c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org { 921c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 922c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org // Pass the function and deoptimization type to the runtime system. 923c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org __ li(a0, Operand(Smi::FromInt(static_cast<int>(type)))); 924c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org __ push(a0); 925c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org __ CallRuntime(Runtime::kNotifyDeoptimized, 1); 926c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org } 927c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org 928c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org // Get the full codegen state from the stack and untag it -> t2. 929c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org __ lw(t2, MemOperand(sp, 0 * kPointerSize)); 930c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org __ SmiUntag(t2); 931c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org // Switch on the state. 932c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org Label with_tos_register, unknown_state; 933c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org __ Branch(&with_tos_register, 934c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org ne, t2, Operand(FullCodeGenerator::NO_REGISTERS)); 9358a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org __ Ret(USE_DELAY_SLOT); 9368a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org // Safe to fill delay slot Addu will emit one instruction. 937c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org __ Addu(sp, sp, Operand(1 * kPointerSize)); // Remove state. 938c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org 939c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org __ bind(&with_tos_register); 940c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org __ lw(v0, MemOperand(sp, 1 * kPointerSize)); 941c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org __ Branch(&unknown_state, ne, t2, Operand(FullCodeGenerator::TOS_REG)); 942c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org 9438a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org __ Ret(USE_DELAY_SLOT); 9448a00e82ec5c3dbedfd3dcb56996c7df2452da4a5verwaest@chromium.org // Safe to fill delay slot Addu will emit one instruction. 945c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org __ Addu(sp, sp, Operand(2 * kPointerSize)); // Remove state. 946c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org 947c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org __ bind(&unknown_state); 948c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org __ stop("no cases left"); 949c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org} 950c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org 951c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org 9527516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) { 953c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::EAGER); 9547516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org} 9557516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 9567516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 9570410973aac1fa3a7aa16285ba799f531983bc916palfia@homejinni.comvoid Builtins::Generate_NotifySoftDeoptimized(MacroAssembler* masm) { 9580410973aac1fa3a7aa16285ba799f531983bc916palfia@homejinni.com Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::SOFT); 9590410973aac1fa3a7aa16285ba799f531983bc916palfia@homejinni.com} 9600410973aac1fa3a7aa16285ba799f531983bc916palfia@homejinni.com 9610410973aac1fa3a7aa16285ba799f531983bc916palfia@homejinni.com 9627516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Builtins::Generate_NotifyLazyDeoptimized(MacroAssembler* masm) { 963c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY); 9647516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org} 9657516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 9667516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org 9677516f05132429850aa326421ed3e25f23b4c071blrn@chromium.orgvoid Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { 968e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org // Lookup the function in the JavaScript frame. 969c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org __ lw(a0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 970c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org { 971c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 972e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org // Lookup and calculate pc offset. 973e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org __ lw(a1, MemOperand(fp, StandardFrameConstants::kCallerPCOffset)); 974e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org __ lw(a2, FieldMemOperand(a0, JSFunction::kSharedFunctionInfoOffset)); 975e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org __ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kCodeOffset)); 976e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org __ Subu(a1, a1, Operand(Code::kHeaderSize - kHeapObjectTag)); 977e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org __ Subu(a1, a1, a2); 978e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org __ SmiTag(a1); 979e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org 980e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org // Pass both function and pc offset as arguments. 981c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org __ push(a0); 982e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org __ push(a1); 983e97852de34e44a479f092bd2449134e707cd9cf1dslomov@chromium.org __ CallRuntime(Runtime::kCompileForOnStackReplacement, 2); 984c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org } 985c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org 986c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org // If the code object is null, just return to the unoptimized code. 987c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org __ Ret(eq, v0, Operand(Smi::FromInt(0))); 988c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org 989c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org // Load deoptimization data from the code object. 990c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org // <deopt_data> = <code>[#deoptimization_data_offset] 991c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org __ lw(a1, MemOperand(v0, Code::kDeoptimizationDataOffset - kHeapObjectTag)); 992c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org 993c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org // Load the OSR entrypoint offset from the deoptimization data. 994c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org // <osr_offset> = <deopt_data>[#header_size + #osr_pc_offset] 995c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org __ lw(a1, MemOperand(a1, FixedArray::OffsetOfElementAt( 996c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org DeoptimizationInputData::kOsrPcOffsetIndex) - kHeapObjectTag)); 997c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org __ SmiUntag(a1); 998c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org 999c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org // Compute the target address = code_obj + header_size + osr_offset 1000c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org // <entry_addr> = <code_obj> + #header_size + <osr_offset> 1001c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org __ addu(v0, v0, a1); 1002c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org __ addiu(ra, v0, Code::kHeaderSize - kHeapObjectTag); 1003c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org 1004c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org // And "return" to the OSR entry point of the function. 1005c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org __ Ret(); 10065c838251403b0be9a882540f1922577abba4c872ager@chromium.org} 10075c838251403b0be9a882540f1922577abba4c872ager@chromium.org 10085c838251403b0be9a882540f1922577abba4c872ager@chromium.org 10098e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.orgvoid Builtins::Generate_OsrAfterStackCheck(MacroAssembler* masm) { 10108e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org // We check the stack limit as indicator that recompilation might be done. 10118e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org Label ok; 10128e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org __ LoadRoot(at, Heap::kStackLimitRootIndex); 10138e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org __ Branch(&ok, hs, sp, Operand(at)); 10148e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org { 10158e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org FrameScope scope(masm, StackFrame::INTERNAL); 10168e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org __ CallRuntime(Runtime::kStackGuard, 0); 10178e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org } 10188e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org __ Jump(masm->isolate()->builtins()->OnStackReplacement(), 10198e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org RelocInfo::CODE_TARGET); 10208e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org 10218e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org __ bind(&ok); 10228e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org __ Ret(); 10238e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org} 10248e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org 10258e36b5ba34174c8ceb04a47d7e10dcc8f43d94a4machenbach@chromium.org 10265c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Builtins::Generate_FunctionCall(MacroAssembler* masm) { 10277304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // 1. Make sure we have at least one argument. 10287304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a0: actual number of arguments 10297304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org { Label done; 10307304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Branch(&done, ne, a0, Operand(zero_reg)); 10317304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ LoadRoot(t2, Heap::kUndefinedValueRootIndex); 10327304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ push(t2); 10337304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Addu(a0, a0, Operand(1)); 10347304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ bind(&done); 10357304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org } 10367304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 10377304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // 2. Get the function to call (passed as receiver) from the stack, check 10387304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // if it is a function. 10397304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a0: actual number of arguments 1040c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label slow, non_function; 10417304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ sll(at, a0, kPointerSizeLog2); 10427304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ addu(at, sp, at); 10437304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ lw(a1, MemOperand(at)); 1044c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org __ JumpIfSmi(a1, &non_function); 10457304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ GetObjectType(a1, a2, a2); 1046c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Branch(&slow, ne, a2, Operand(JS_FUNCTION_TYPE)); 10477304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 10487304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // 3a. Patch the first argument if necessary when calling a function. 10497304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a0: actual number of arguments 10507304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a1: function 10517304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org Label shift_arguments; 105259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ li(t0, Operand(0, RelocInfo::NONE32)); // Indicate regular JS_FUNCTION. 10537304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org { Label convert_to_object, use_global_receiver, patch_receiver; 10547304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Change context eagerly in case we need the global receiver. 10557304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); 10567304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 10577304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Do not transform the receiver for strict mode functions. 10587304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); 10597304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ lw(a3, FieldMemOperand(a2, SharedFunctionInfo::kCompilerHintsOffset)); 1060c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ And(t3, a3, Operand(1 << (SharedFunctionInfo::kStrictModeFunction + 10617304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org kSmiTagSize))); 1062c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Branch(&shift_arguments, ne, t3, Operand(zero_reg)); 10637304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 106440cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org // Do not transform the receiver for native (Compilerhints already in a3). 1065c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ And(t3, a3, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize))); 1066c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Branch(&shift_arguments, ne, t3, Operand(zero_reg)); 10677304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 10687304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Compute the receiver in non-strict mode. 10697304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Load first argument in a2. a2 = -kPointerSize(sp + n_args << 2). 10707304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ sll(at, a0, kPointerSizeLog2); 10717304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ addu(a2, sp, at); 10727304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ lw(a2, MemOperand(a2, -kPointerSize)); 10737304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a0: actual number of arguments 10747304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a1: function 10757304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a2: first argument 10767304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ JumpIfSmi(a2, &convert_to_object, t2); 10777304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 107840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ LoadRoot(a3, Heap::kUndefinedValueRootIndex); 10797304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Branch(&use_global_receiver, eq, a2, Operand(a3)); 10807304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ LoadRoot(a3, Heap::kNullValueRootIndex); 10817304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Branch(&use_global_receiver, eq, a2, Operand(a3)); 10827304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 1083d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); 10847304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ GetObjectType(a2, a3, a3); 1085d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com __ Branch(&shift_arguments, ge, a3, Operand(FIRST_SPEC_OBJECT_TYPE)); 10867304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 10877304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ bind(&convert_to_object); 1088c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Enter an internal frame in order to preserve argument count. 1089c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { 1090c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com FrameScope scope(masm, StackFrame::INTERNAL); 1091c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sll(a0, a0, kSmiTagSize); // Smi tagged. 1092c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(a0); 1093c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1094c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(a2); 1095c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 1096c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(a2, v0); 1097c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1098c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ pop(a0); 1099c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sra(a0, a0, kSmiTagSize); // Un-tag. 1100c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Leave internal frame. 1101c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 1102c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Restore the function to a1, and the flag to t0. 11037304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ sll(at, a0, kPointerSizeLog2); 11047304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ addu(at, sp, at); 11057304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ lw(a1, MemOperand(at)); 110659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ li(t0, Operand(0, RelocInfo::NONE32)); 11077304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Branch(&patch_receiver); 11087304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 11097304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Use the global receiver object from the called function as the 11107304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // receiver. 11117304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ bind(&use_global_receiver); 11127304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org const int kGlobalIndex = 111346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize; 11147304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ lw(a2, FieldMemOperand(cp, kGlobalIndex)); 111546839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org __ lw(a2, FieldMemOperand(a2, GlobalObject::kNativeContextOffset)); 11167304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ lw(a2, FieldMemOperand(a2, kGlobalIndex)); 11177304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalReceiverOffset)); 11187304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 11197304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ bind(&patch_receiver); 11207304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ sll(at, a0, kPointerSizeLog2); 11217304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ addu(a3, sp, at); 11227304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ sw(a2, MemOperand(a3, -kPointerSize)); 11237304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 11247304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Branch(&shift_arguments); 11257304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org } 11267304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 1127c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // 3b. Check for function proxy. 1128c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&slow); 112959297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ li(t0, Operand(1, RelocInfo::NONE32)); // Indicate function proxy. 1130c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Branch(&shift_arguments, eq, a2, Operand(JS_FUNCTION_PROXY_TYPE)); 1131c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1132c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&non_function); 113359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ li(t0, Operand(2, RelocInfo::NONE32)); // Indicate non-function. 1134c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1135c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // 3c. Patch the first argument when calling a non-function. The 11367304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // CALL_NON_FUNCTION builtin expects the non-function callee as 11377304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // receiver, so overwrite the first argument which will ultimately 11387304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // become the receiver. 11397304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a0: actual number of arguments 11407304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a1: function 1141c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // t0: call type (0: JS function, 1: function proxy, 2: non-function) 11427304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ sll(at, a0, kPointerSizeLog2); 11437304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ addu(a2, sp, at); 11447304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ sw(a1, MemOperand(a2, -kPointerSize)); 11457304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 11467304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // 4. Shift arguments and return address one slot down on the stack 11477304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // (overwriting the original receiver). Adjust argument count to make 11487304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // the original first argument the new receiver. 11497304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a0: actual number of arguments 11507304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a1: function 1151c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // t0: call type (0: JS function, 1: function proxy, 2: non-function) 11527304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ bind(&shift_arguments); 11537304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org { Label loop; 11547304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Calculate the copy start address (destination). Copy end address is sp. 11557304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ sll(at, a0, kPointerSizeLog2); 11567304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ addu(a2, sp, at); 11577304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 11587304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ bind(&loop); 11597304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ lw(at, MemOperand(a2, -kPointerSize)); 11607304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ sw(at, MemOperand(a2)); 11617304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Subu(a2, a2, Operand(kPointerSize)); 11627304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Branch(&loop, ne, a2, Operand(sp)); 11637304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Adjust the actual number of arguments and remove the top element 11647304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // (which is a copy of the last argument). 11657304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Subu(a0, a0, Operand(1)); 11667304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Pop(); 11677304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org } 11687304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 1169c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // 5a. Call non-function via tail call to CALL_NON_FUNCTION builtin, 1170c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // or a function proxy via CALL_FUNCTION_PROXY. 11717304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a0: actual number of arguments 11727304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a1: function 1173c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // t0: call type (0: JS function, 1: function proxy, 2: non-function) 1174c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { Label function, non_proxy; 1175c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Branch(&function, eq, t0, Operand(zero_reg)); 1176c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Expected number of arguments is 0 for CALL_NON_FUNCTION. 1177c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(a2, zero_reg); 117840cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ SetCallKind(t1, CALL_AS_METHOD); 1179c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Branch(&non_proxy, ne, t0, Operand(1)); 1180c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1181c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(a1); // Re-add proxy object as additional argument. 1182c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Addu(a0, a0, Operand(1)); 1183c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ GetBuiltinEntry(a3, Builtins::CALL_FUNCTION_PROXY); 1184c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 1185c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com RelocInfo::CODE_TARGET); 1186c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1187c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&non_proxy); 1188c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION); 11897304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 11907304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org RelocInfo::CODE_TARGET); 11917304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ bind(&function); 11927304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org } 11937304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 11947304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // 5b. Get the code to call from the function and check that the number of 11957304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // expected arguments matches what we're providing. If so, jump 11967304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // (tail-call) to the code in register edx without checking arguments. 11977304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a0: actual number of arguments 11987304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a1: function 11997304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ lw(a3, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); 12007304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ lw(a2, 12017304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org FieldMemOperand(a3, SharedFunctionInfo::kFormalParameterCountOffset)); 12027304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ sra(a2, a2, kSmiTagSize); 12037304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); 120440cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org __ SetCallKind(t1, CALL_AS_METHOD); 12057304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Check formal and actual parameter counts. 12067304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 12077304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org RelocInfo::CODE_TARGET, ne, a2, Operand(a0)); 12087304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 12097304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org ParameterCount expected(0); 1210d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com __ InvokeCode(a3, expected, expected, JUMP_FUNCTION, 1211d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com NullCallWrapper(), CALL_AS_METHOD); 12125c838251403b0be9a882540f1922577abba4c872ager@chromium.org} 12135c838251403b0be9a882540f1922577abba4c872ager@chromium.org 12145c838251403b0be9a882540f1922577abba4c872ager@chromium.org 12155c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Builtins::Generate_FunctionApply(MacroAssembler* masm) { 12167ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org const int kIndexOffset = 12177ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize); 12187ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org const int kLimitOffset = 12197ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize); 12207ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org const int kArgsOffset = 2 * kPointerSize; 12217ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org const int kRecvOffset = 3 * kPointerSize; 12227ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org const int kFunctionOffset = 4 * kPointerSize; 12237304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 1224c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com { 1225c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org FrameScope frame_scope(masm, StackFrame::INTERNAL); 1226c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(a0, MemOperand(fp, kFunctionOffset)); // Get the function. 1227c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(a0); 1228c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(a0, MemOperand(fp, kArgsOffset)); // Get the args array. 1229c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(a0); 1230c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Returns (in v0) number of arguments to copy to stack as Smi. 1231c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); 1232c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1233c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Check the stack for overflow. We are not trying to catch 1234c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // interruptions (e.g. debug break and preemption) here, so the "real stack 1235c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // limit" is checked. 1236c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label okay; 1237c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ LoadRoot(a2, Heap::kRealStackLimitRootIndex); 1238c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Make a2 the space we have left. The stack might already be overflowed 1239c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // here which will cause a2 to become negative. 1240c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ subu(a2, sp, a2); 1241c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Check if the arguments will overflow the stack. 1242c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sll(t3, v0, kPointerSizeLog2 - kSmiTagSize); 1243c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Branch(&okay, gt, a2, Operand(t3)); // Signed comparison. 1244c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1245c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Out of stack space. 1246c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(a1, MemOperand(fp, kFunctionOffset)); 1247057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org __ Push(a1, v0); 1248c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION); 1249c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // End of stack check. 1250c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1251c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Push current limit and index. 1252c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&okay); 1253c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(v0); // Limit. 1254c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(a1, zero_reg); // Initial index. 1255c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(a1); 12567304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 1257c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Get the receiver. 1258c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(a0, MemOperand(fp, kRecvOffset)); 12597304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 1260c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Check that the function is a JS function (otherwise it must be a proxy). 1261c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label push_receiver; 1262c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(a1, MemOperand(fp, kFunctionOffset)); 1263c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ GetObjectType(a1, a2, a2); 1264c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Branch(&push_receiver, ne, a2, Operand(JS_FUNCTION_TYPE)); 12657304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 1266c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Change context eagerly to get the right global object if necessary. 1267c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); 1268c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Load the shared function info while the function is still in a1. 1269c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); 12707304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 1271c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Compute the receiver. 1272c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Do not transform the receiver for strict mode functions. 1273c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label call_to_object, use_global_receiver; 1274c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kCompilerHintsOffset)); 1275c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ And(t3, a2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction + 1276c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com kSmiTagSize))); 1277c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Branch(&push_receiver, ne, t3, Operand(zero_reg)); 1278c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1279c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Do not transform the receiver for native (Compilerhints already in a2). 1280c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ And(t3, a2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize))); 1281c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Branch(&push_receiver, ne, t3, Operand(zero_reg)); 1282c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1283c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Compute the receiver in non-strict mode. 1284c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org __ JumpIfSmi(a0, &call_to_object); 1285c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ LoadRoot(a1, Heap::kNullValueRootIndex); 1286c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Branch(&use_global_receiver, eq, a0, Operand(a1)); 1287c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); 1288c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Branch(&use_global_receiver, eq, a0, Operand(a2)); 1289c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1290c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Check if the receiver is already a JavaScript object. 1291c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a0: receiver 1292c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); 1293c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ GetObjectType(a0, a1, a1); 1294c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Branch(&push_receiver, ge, a1, Operand(FIRST_SPEC_OBJECT_TYPE)); 1295c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1296c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Convert the receiver to a regular object. 1297c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a0: receiver 1298c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&call_to_object); 1299c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(a0); 1300c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 1301c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ mov(a0, v0); // Put object in a0 to match other paths to push_receiver. 1302c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Branch(&push_receiver); 1303c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1304c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Use the current global receiver object as the receiver. 1305c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&use_global_receiver); 1306c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com const int kGlobalOffset = 130746839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org Context::kHeaderSize + Context::GLOBAL_OBJECT_INDEX * kPointerSize; 1308c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(a0, FieldMemOperand(cp, kGlobalOffset)); 130946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org __ lw(a0, FieldMemOperand(a0, GlobalObject::kNativeContextOffset)); 1310c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(a0, FieldMemOperand(a0, kGlobalOffset)); 1311c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(a0, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset)); 1312c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1313c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Push the receiver. 1314c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a0: receiver 1315c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&push_receiver); 1316c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(a0); 1317c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1318c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Copy all arguments from the array to the stack. 1319c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label entry, loop; 1320c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(a0, MemOperand(fp, kIndexOffset)); 1321c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Branch(&entry); 1322c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1323c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Load the current argument from the arguments array and push it to the 1324c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // stack. 1325c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // a0: current argument index 1326c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&loop); 1327c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(a1, MemOperand(fp, kArgsOffset)); 1328057bd50c2c2d15923523777a296cddee5c8ba63bverwaest@chromium.org __ Push(a1, a0); 1329c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1330c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Call the runtime to access the property in the arguments array. 1331c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ CallRuntime(Runtime::kGetProperty, 2); 1332c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(v0); 1333c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1334c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Use inline caching to access the arguments. 1335c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(a0, MemOperand(fp, kIndexOffset)); 1336c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Addu(a0, a0, Operand(1 << kSmiTagSize)); 1337c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sw(a0, MemOperand(fp, kIndexOffset)); 1338c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1339c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Test if the copy loop has finished copying all the elements from the 1340c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // arguments object. 1341c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&entry); 1342c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(a1, MemOperand(fp, kLimitOffset)); 1343c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Branch(&loop, ne, a0, Operand(a1)); 1344c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1345c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Invoke the function. 1346c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com Label call_proxy; 1347c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com ParameterCount actual(a0); 1348c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ sra(a0, a0, kSmiTagSize); 1349c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ lw(a1, MemOperand(fp, kFunctionOffset)); 1350c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ GetObjectType(a1, a2, a2); 1351c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Branch(&call_proxy, ne, a2, Operand(JS_FUNCTION_TYPE)); 1352c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1353c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ InvokeFunction(a1, actual, CALL_FUNCTION, 1354c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com NullCallWrapper(), CALL_AS_METHOD); 1355c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1356c3b37129d6387b2db313f9100256d2d5f60dd9a8jkummerow@chromium.org frame_scope.GenerateLeaveFrame(); 1357c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Ret(USE_DELAY_SLOT); 1358c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Addu(sp, sp, Operand(3 * kPointerSize)); // In delay slot. 1359c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1360c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Invoke the function proxy. 1361c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ bind(&call_proxy); 1362c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ push(a1); // Add function proxy as last argument. 1363c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Addu(a0, a0, Operand(1)); 136459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org __ li(a2, Operand(0, RelocInfo::NONE32)); 1365c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ SetCallKind(t1, CALL_AS_METHOD); 1366c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ GetBuiltinEntry(a3, Builtins::CALL_FUNCTION_PROXY); 1367c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), 1368c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com RelocInfo::CODE_TARGET); 1369c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com // Tear down the internal frame and remove function, receiver and args. 1370c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com } 1371c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com 1372c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Ret(USE_DELAY_SLOT); 1373c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com __ Addu(sp, sp, Operand(3 * kPointerSize)); // In delay slot. 13747304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org} 13757304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 13767304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 13777304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgstatic void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { 13787304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ sll(a0, a0, kSmiTagSize); 13797304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ li(t0, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 13807304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ MultiPush(a0.bit() | a1.bit() | t0.bit() | fp.bit() | ra.bit()); 13817ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org __ Addu(fp, sp, 13827ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org Operand(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize)); 13837304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org} 13847304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 13857304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 13867304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.orgstatic void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) { 13877304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // ----------- S t a t e ------------- 13887304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- v0 : result being passed through 13897304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // ----------------------------------- 13907304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Get the number of arguments passed (as a smi), tear down the frame and 13917304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // then tear down the parameters. 13927ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org __ lw(a1, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp + 13937ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org kPointerSize))); 13947304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ mov(sp, fp); 13957304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ MultiPop(fp.bit() | ra.bit()); 13967304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ sll(t0, a1, kPointerSizeLog2 - kSmiTagSize); 13977304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Addu(sp, sp, t0); 13987304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Adjust for the receiver. 13997304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Addu(sp, sp, Operand(kPointerSize)); 14005c838251403b0be9a882540f1922577abba4c872ager@chromium.org} 14015c838251403b0be9a882540f1922577abba4c872ager@chromium.org 14025c838251403b0be9a882540f1922577abba4c872ager@chromium.org 14035c838251403b0be9a882540f1922577abba4c872ager@chromium.orgvoid Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { 14047304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // State setup as expected by MacroAssembler::InvokePrologue. 14057304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // ----------- S t a t e ------------- 14067304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- a0: actual arguments count 14077304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- a1: function (passed through to callee) 14087304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- a2: expected arguments count 14097304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // -- a3: callee code entry 141040cb878ef373bea9bdf7998829891e4096751dd0danno@chromium.org // -- t1: call kind information 14117304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // ----------------------------------- 14127304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 14137304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org Label invoke, dont_adapt_arguments; 14147304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 14157304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org Label enough, too_few; 14167304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Branch(&dont_adapt_arguments, eq, 14177304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org a2, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel)); 14187304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // We use Uless as the number of argument should always be greater than 0. 14197304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Branch(&too_few, Uless, a0, Operand(a2)); 14207304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 14217304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org { // Enough parameters: actual >= expected. 14227304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a0: actual number of arguments as a smi 14237304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a1: function 14247304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a2: expected number of arguments 14257304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a3: code entry to call 14267304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ bind(&enough); 14277304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org EnterArgumentsAdaptorFrame(masm); 14287304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 14297304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Calculate copy start address into a0 and copy end address into a2. 14307304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ sll(a0, a0, kPointerSizeLog2 - kSmiTagSize); 14317304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Addu(a0, fp, a0); 14327304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Adjust for return address and receiver. 14337304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Addu(a0, a0, Operand(2 * kPointerSize)); 14347304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Compute copy end address. 14357304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ sll(a2, a2, kPointerSizeLog2); 14367304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ subu(a2, a0, a2); 14377304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 14387304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Copy the arguments (including the receiver) to the new stack frame. 14397304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a0: copy start address 14407304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a1: function 14417304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a2: copy end address 14427304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a3: code entry to call 14437304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 14447304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org Label copy; 14457304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ bind(©); 14467304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ lw(t0, MemOperand(a0)); 14477304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ push(t0); 14487304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Branch(USE_DELAY_SLOT, ©, ne, a0, Operand(a2)); 14497304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ addiu(a0, a0, -kPointerSize); // In delay slot. 14507304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 14517304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ jmp(&invoke); 14527304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org } 14537304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 14547304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org { // Too few parameters: Actual < expected. 14557304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ bind(&too_few); 14567304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org EnterArgumentsAdaptorFrame(masm); 14577304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 14587304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Calculate copy start address into a0 and copy end address is fp. 14597304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a0: actual number of arguments as a smi 14607304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a1: function 14617304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a2: expected number of arguments 14627304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a3: code entry to call 14637304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ sll(a0, a0, kPointerSizeLog2 - kSmiTagSize); 14647304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Addu(a0, fp, a0); 14657304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Adjust for return address and receiver. 14667304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Addu(a0, a0, Operand(2 * kPointerSize)); 14677304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Compute copy end address. Also adjust for return address. 1468d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com __ Addu(t3, fp, kPointerSize); 14697304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 14707304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Copy the arguments (including the receiver) to the new stack frame. 14717304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a0: copy start address 14727304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a1: function 14737304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a2: expected number of arguments 14747304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a3: code entry to call 1475d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com // t3: copy end address 14767304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org Label copy; 14777304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ bind(©); 14787304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ lw(t0, MemOperand(a0)); // Adjusted above for return addr and receiver. 1479bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com __ Subu(sp, sp, kPointerSize); 14807304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Subu(a0, a0, kPointerSize); 1481bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com __ Branch(USE_DELAY_SLOT, ©, ne, a0, Operand(t3)); 1482bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com __ sw(t0, MemOperand(sp)); // In the delay slot. 14837304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 14847304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Fill the remaining expected arguments with undefined. 14857304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a1: function 14867304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a2: expected number of arguments 14877304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // a3: code entry to call 14887304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ LoadRoot(t0, Heap::kUndefinedValueRootIndex); 14897304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ sll(t2, a2, kPointerSizeLog2); 14907304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Subu(a2, fp, Operand(t2)); 14917ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org // Adjust for frame. 14927ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org __ Subu(a2, a2, Operand(StandardFrameConstants::kFixedFrameSizeFromFp + 14937ff7607c2315ea91e4d13330ce14125e4bb4851amachenbach@chromium.org 2 * kPointerSize)); 14947304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 14957304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org Label fill; 14967304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ bind(&fill); 1497bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com __ Subu(sp, sp, kPointerSize); 1498bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com __ Branch(USE_DELAY_SLOT, &fill, ne, sp, Operand(a2)); 1499bbceb57d27ec53f6d6212e690ead3174192ea3f9erik.corry@gmail.com __ sw(t0, MemOperand(sp)); 15007304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org } 15017304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 15027304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Call the entry point. 15037304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ bind(&invoke); 15047304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 15057304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Call(a3); 15067304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 1507812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org // Store offset of return address for deoptimizer. 1508fa458e413c3e5b8d479e49258d060b7bb4567c57danno@chromium.org masm->isolate()->heap()->SetArgumentsAdaptorDeoptPCOffset(masm->pc_offset()); 1509812308e1488cd8261e4dbbda1d8022642d522b9bulan@chromium.org 15107304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Exit frame and return. 15117304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org LeaveArgumentsAdaptorFrame(masm); 15127304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Ret(); 15137304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 15147304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org 15157304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // ------------------------------------------- 15167304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // Don't adapt arguments. 15177304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org // ------------------------------------------- 15187304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ bind(&dont_adapt_arguments); 15197304bcac06a6a63b9f3dcebac2eeceada87ca146vegorov@chromium.org __ Jump(a3); 15205c838251403b0be9a882540f1922577abba4c872ager@chromium.org} 15215c838251403b0be9a882540f1922577abba4c872ager@chromium.org 15225c838251403b0be9a882540f1922577abba4c872ager@chromium.org 15235c838251403b0be9a882540f1922577abba4c872ager@chromium.org#undef __ 15245c838251403b0be9a882540f1922577abba4c872ager@chromium.org 15255c838251403b0be9a882540f1922577abba4c872ager@chromium.org} } // namespace v8::internal 15265c838251403b0be9a882540f1922577abba4c872ager@chromium.org 15279dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com#endif // V8_TARGET_ARCH_MIPS 1528