13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h" 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_X64 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-factory.h" 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/code-stubs.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h" 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/compiler.h" 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/debug.h" 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/full-codegen.h" 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic.h" 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/isolate-inl.h" 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/parser.h" 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/scopes.h" 193ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 203ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace v8 { 213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace internal { 223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#define __ ACCESS_MASM(masm_) 243ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockclass JumpPatchSite BASE_EMBEDDED { 271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block public: 28589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) { 291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG 301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block info_emitted_ = false; 311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif 321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ~JumpPatchSite() { 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(patch_site_.is_bound() == info_emitted_); 361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 38257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void EmitJumpIfNotSmi(Register reg, 39257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* target, 40257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar) { 411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testb(reg, Immediate(kSmiTagMask)); 42257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitJump(not_carry, target, near_jump); // Always taken before patched. 431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 45257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void EmitJumpIfSmi(Register reg, 46257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* target, 47257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label::Distance near_jump = Label::kFar) { 481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testb(reg, Immediate(kSmiTagMask)); 49257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitJump(carry, target, near_jump); // Never taken before patched. 501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void EmitPatchInfo() { 533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (patch_site_.is_bound()) { 543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_); 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(is_uint8(delta_to_patch_site)); 563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ testl(rax, Immediate(delta_to_patch_site)); 571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG 583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch info_emitted_ = true; 591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif 603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ nop(); // Signals no inlined code. 623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block private: 661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // jc will be patched with jz, jnc will become jnz. 67257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void EmitJump(Condition cc, Label* target, Label::Distance near_jump) { 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!patch_site_.is_bound() && !info_emitted_); 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(cc == carry || cc == not_carry); 701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&patch_site_); 71257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(cc, target, near_jump); 721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block MacroAssembler* masm_; 751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label patch_site_; 761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG 771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool info_emitted_; 781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif 791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}; 801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Generate code for a JS function. On entry to the function the receiver 833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// and arguments have been pushed on the stack left to right, with the 843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// return address on top of them. The actual argument count matches the 853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// formal parameter count expected by the function. 863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The live registers are: 883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// o rdi: the JS function object being called (i.e. ourselves) 893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o rsi: our context 903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o rbp: our caller's frame pointer 913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// o rsp: stack pointer (pointing to return address) 923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// 933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// The function builds a JS frame. Please see JavaScriptFrameConstants in 943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// frames-x64.h for its layout. 953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::Generate() { 963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompilationInfo* info = info_; 973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch handler_table_ = 983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED); 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch profiling_counter_ = isolate()->factory()->NewCell( 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate())); 1023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu SetFunctionPosition(function()); 1036ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Comment cmnt(masm_, "[ function compiled by full code generator"); 1043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ProfileEntryHookStub::MaybeCallEntryHook(masm_); 1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 107f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#ifdef DEBUG 108f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if (strlen(FLAG_stop_at) > 0 && 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { 110f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ int3(); 111f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch } 112f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#endif 113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Sloppy mode functions and builtins need to replace the receiver with the 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // global proxy when called as functions (without an explicit receiver 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // object). 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (info->strict_mode() == SLOPPY && !info->is_native()) { 118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label ok; 119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // +1 for return address. 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StackArgumentsAccessor args(rsp, info->scope()->num_parameters()); 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, args.GetReceiverOperand()); 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex); 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &ok, Label::kNear); 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, GlobalObjectOperand()); 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, FieldOperand(rcx, GlobalObject::kGlobalProxyOffset)); 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(args.GetReceiverOperand(), rcx); 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&ok); 132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Open a frame scope to indicate that there is a frame on the stack. The 1353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // MANUAL indicates that the scope shouldn't actually generate code to set up 1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the frame (that is done below). 1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope frame_scope(masm_, StackFrame::MANUAL); 1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info->set_prologue_offset(masm_->pc_offset()); 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Prologue(info->IsCodePreAgingActive()); 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info->AddNoFrameRange(0, masm_->pc_offset()); 142756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 143756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick { Comment cmnt(masm_, "[ Allocate locals"); 1443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int locals_count = info->scope()->num_stack_slots(); 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generators allocate locals, if any, in context slots. 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!info->function()->is_generator() || locals_count == 0); 147756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (locals_count == 1) { 148756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ PushRoot(Heap::kUndefinedValueRootIndex); 149756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else if (locals_count > 1) { 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (locals_count >= 128) { 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label ok; 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, rsp); 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(rcx, Immediate(locals_count * kPointerSize)); 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(rcx, Heap::kRealStackLimitRootIndex); 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(above_equal, &ok, Label::kNear); 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeBuiltin(Builtins::STACK_OVERFLOW, CALL_FUNCTION); 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&ok); 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 159756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex); 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kMaxPushes = 32; 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (locals_count >= kMaxPushes) { 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int loop_iterations = locals_count / kMaxPushes; 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, Immediate(loop_iterations)); 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label loop_header; 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&loop_header); 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do pushes. 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < kMaxPushes; i++) { 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdx); 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Continue loop if not done. 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ decp(rcx); 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &loop_header, Label::kNear); 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int remaining = locals_count % kMaxPushes; 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit the remaining pushes. 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < remaining; i++) { 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdx); 178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 179d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 180756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 181d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 182756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick bool function_in_register = true; 1834515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 184756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Possibly allocate a local context. 1853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 186756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (heap_slots > 0) { 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Allocate context"); 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool need_write_barrier = true; 189756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Argument to NewContext is the function, which is still in rdi. 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_harmony_scoping && info->scope()->is_global_scope()) { 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdi); 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(info->scope()->GetScopeInfo()); 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kNewGlobalContext, 2); 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (heap_slots <= FastNewContextStub::kMaximumSlots) { 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FastNewContextStub stub(isolate(), heap_slots); 196756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ CallStub(&stub); 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Result of FastNewContextStub is always in new space. 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch need_write_barrier = false; 199756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else { 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdi); 2013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CallRuntime(Runtime::kNewFunctionContext, 1); 202756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 203756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick function_in_register = false; 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Context is returned in rax. It replaces the context passed to us. 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // It's saved in the stack and kept live in rsi. 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rsi, rax); 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rax); 208756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 209756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Copy any necessary parameters into the context. 2103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int num_parameters = info->scope()->num_parameters(); 211756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick for (int i = 0; i < num_parameters; i++) { 212589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* var = scope()->parameter(i); 213589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 214756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick int parameter_offset = StandardFrameConstants::kCallerSPOffset + 215756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick (num_parameters - 1 - i) * kPointerSize; 216756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Load parameter from stack. 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, Operand(rbp, parameter_offset)); 218756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Store it in the context. 219589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int context_offset = Context::SlotOffset(var->index()); 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rsi, context_offset), rax); 2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Update the write barrier. This clobbers rax and rbx. 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (need_write_barrier) { 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteContextSlot( 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch rsi, context_offset, rax, rbx, kDontSaveFPRegs); 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (FLAG_debug_code) { 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfInNewSpace(rsi, rax, &done, Label::kNear); 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Abort(kExpectedNewSpaceObject); 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2323ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 233756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } 2343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 235756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Possibly allocate an arguments object. 2360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Variable* arguments = scope()->arguments(); 237756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (arguments != NULL) { 238756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Arguments object must be allocated after the context object, in 239756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // case the "arguments" or ".arguments" variables are in the context. 240756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Comment cmnt(masm_, "[ Allocate arguments object"); 241756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick if (function_in_register) { 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdi); 243756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick } else { 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 246756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // The receiver is just before the parameters on the caller's stack. 2473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int num_parameters = info->scope()->num_parameters(); 2483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int offset = num_parameters * kPointerSize; 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(rdx, 250756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset)); 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdx); 2523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Push(Smi::FromInt(num_parameters)); 253756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // Arguments to ArgumentsAccessStub: 254756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // function, receiver address, parameter count. 255756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // The stub will rewrite receiver and parameter count if the previous 256756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick // stack frame was an arguments adapter frame. 2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ArgumentsAccessStub::Type type; 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (strict_mode() == STRICT) { 2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch type = ArgumentsAccessStub::NEW_STRICT; 2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (function()->has_duplicate_parameters()) { 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch type = ArgumentsAccessStub::NEW_SLOPPY_SLOW; 2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch type = ArgumentsAccessStub::NEW_SLOPPY_FAST; 2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArgumentsAccessStub stub(isolate(), type); 266756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick __ CallStub(&stub); 26744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 268589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch SetVar(arguments, rax, rbx, rdx); 269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace) { 272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ CallRuntime(Runtime::kTraceEnter, 0); 273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 275e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Visit the declarations and body unless there is an illegal 276e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // redeclaration. 277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (scope()->HasIllegalRedeclaration()) { 278e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Comment cmnt(masm_, "[ Declarations"); 279e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch scope()->VisitIllegalRedeclaration(this); 280589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 281e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); 283e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch { Comment cmnt(masm_, "[ Declarations"); 284e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // For named function expressions, declare the function name as a 285e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // constant. 286e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (scope()->is_function_scope() && scope()->function() != NULL) { 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableDeclaration* function = scope()->function(); 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(function->proxy()->var()->mode() == CONST || 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch function->proxy()->var()->mode() == CONST_LEGACY); 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(function->proxy()->var()->location() != Variable::UNALLOCATED); 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitVariableDeclaration(function); 292e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 293e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitDeclarations(scope()->declarations()); 294e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 296e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch { Comment cmnt(masm_, "[ Stack check"); 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label ok; 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(above_equal, &ok, Label::kNear); 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET); 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&ok); 303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 305e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch { Comment cmnt(masm_, "[ Body"); 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(loop_depth() == 0); 307e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitStatements(function()->body()); 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(loop_depth() == 0); 309e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 3113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 312e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Always emit a 'return undefined' in case control fell off the end of 313e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // the body. 3143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block { Comment cmnt(masm_, "[ return <undefined>;"); 3153ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 3167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch EmitReturnSequence(); 317d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 318d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 319d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 320d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 321db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdochvoid FullCodeGenerator::ClearAccumulator() { 3229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ Set(rax, 0); 323db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch} 324db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch 325db5a90a88cfcddb042912799e872037c6548b8a3Ben Murdoch 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitProfilingCounterDecrement(int delta) { 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT); 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiAddConstant(FieldOperand(rbx, Cell::kValueOffset), 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(-delta)); 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitProfilingCounterReset() { 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int reset_value = FLAG_interrupt_budget; 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT); 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(kScratchRegister, Smi::FromInt(reset_value)); 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rbx, Cell::kValueOffset), kScratchRegister); 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const byte kJnsOffset = kPointerSize == kInt64Size ? 0x1d : 0x14; 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt, 345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* back_edge_target) { 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Back edge bookkeeping"); 347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label ok; 348e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(back_edge_target->is_bound()); 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target); 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int weight = Min(kMaxBackEdgeWeight, 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Max(1, distance / kCodeSizeMultiplier)); 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitProfilingCounterDecrement(weight); 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(positive, &ok, Label::kNear); 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PredictableCodeSizeScope predictible_code_size_scope(masm_, kJnsOffset); 358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DontEmitDebugCodeScope dont_emit_debug_code_scope(masm_); 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ call(isolate()->builtins()->InterruptCheck(), RelocInfo::CODE_TARGET); 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record a mapping of this PC offset to the OSR id. This is used to find 362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the AST id from the unoptimized code in order to use it as a key into 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the deoptimization input data found in the optimized code. 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RecordBackEdge(stmt->OsrEntryId()); 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitProfilingCounterReset(); 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&ok); 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); 371086aeeaae12517475c22695a200be45495516549Ben Murdoch // Record a mapping of the OSR id to this PC. This is used if the OSR 372086aeeaae12517475c22695a200be45495516549Ben Murdoch // entry becomes the target of a bailout. We don't expect it to be, but 373086aeeaae12517475c22695a200be45495516549Ben Murdoch // we want it to work if it is. 374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS); 375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid FullCodeGenerator::EmitReturnSequence() { 379d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Return sequence"); 380d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (return_label_.is_bound()) { 381d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ jmp(&return_label_); 382d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&return_label_); 3843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (FLAG_trace) { 385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); 3863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kTraceExit, 1); 3873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pretend that the exit is a backwards jump to the entry. 389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int weight = 1; 390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (info_->ShouldSelfOptimize()) { 391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch weight = FLAG_interrupt_budget / FLAG_self_opt_count; 392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int distance = masm_->pc_offset(); 394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch weight = Min(kMaxBackEdgeWeight, 395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Max(1, distance / kCodeSizeMultiplier)); 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitProfilingCounterDecrement(weight); 398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label ok; 399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(positive, &ok, Label::kNear); 400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); 401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ call(isolate()->builtins()->InterruptCheck(), 402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RelocInfo::CODE_TARGET); 403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rax); 404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitProfilingCounterReset(); 405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&ok); 406d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef DEBUG 407d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Add a label for checking the size of the code used for returning. 408d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label check_exit_codesize; 409d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block masm_->bind(&check_exit_codesize); 410d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif 411bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch CodeGenerator::RecordPositions(masm_, function()->end_position() - 1); 4123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ RecordJSReturn(); 4133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Do not use the leave instruction here because it is too short to 4143ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // patch with the code required by the debugger. 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rsp, rbp); 416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ popq(rbp); 417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int no_frame_start = masm_->pc_offset(); 4181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 4193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int arguments_bytes = (info_->scope()->num_parameters() + 1) * kPointerSize; 4201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Ret(arguments_bytes, rcx); 4211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 4223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Add padding that will be overwritten by a debugger breakpoint. We 423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // have just generated at least 7 bytes: "movp rsp, rbp; pop rbp; ret k" 424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // (3 + 1 + 3) for x64 and at least 6 (2 + 1 + 3) bytes for x32. 425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kPadding = Assembler::kJSReturnSequenceLength - 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kPointerSize == kInt64Size ? 7 : 6; 4273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block for (int i = 0; i < kPadding; ++i) { 4283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block masm_->int3(); 4293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 4301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the size of the code used for returning is large enough 4311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // for the debugger's requirements. 432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::kJSReturnSequenceLength <= 4331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); 434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); 4363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 4373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 4383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4393ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 440589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::EffectContext::Plug(Variable* var) const { 441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 4420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 443e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 444e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 445589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const { 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 447589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch codegen()->GetVar(result_register(), var); 4480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 449e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 451589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::StackValueContext::Plug(Variable* var) const { 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 453589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch MemOperand operand = codegen()->VarOperand(var, result_register()); 454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(operand); 455d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 456d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 457d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 458589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::TestContext::Plug(Variable* var) const { 459589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch codegen()->GetVar(result_register(), var); 4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); 4613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch codegen()->DoTest(this); 4620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 463e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4650d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Heap::RootListIndex index) const { 466d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 467d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 468d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4690d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 4700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex index) const { 4710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), index); 4720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 473e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4750d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug( 4760d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex index) const { 4770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ PushRoot(index); 4780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4810d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Heap::RootListIndex index) const { 4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), 483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true, 484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true_label_, 485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch false_label_); 4860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (index == Heap::kUndefinedValueRootIndex || 4870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen index == Heap::kNullValueRootIndex || 4880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen index == Heap::kFalseValueRootIndex) { 489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (false_label_ != fall_through_) __ jmp(false_label_); 4900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (index == Heap::kTrueValueRootIndex) { 491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (true_label_ != fall_through_) __ jmp(true_label_); 4920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 4930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), index); 4943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch codegen()->DoTest(this); 495e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 496d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 497d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4990d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const { 5000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 501e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 502e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 5030d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 5040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Handle<Object> lit) const { 505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (lit->IsSmi()) { 506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SafeMove(result_register(), Smi::cast(*lit)); 507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(result_register(), lit); 509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 511e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 5120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5130d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { 514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (lit->IsSmi()) { 515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SafePush(Smi::cast(*lit)); 516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(lit); 518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 5190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 5200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5220d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Handle<Object> lit) const { 5233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), 524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true, 525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true_label_, 526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch false_label_); 527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!lit->IsUndetectableObject()); // There are no undetectable literals. 5280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) { 529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (false_label_ != fall_through_) __ jmp(false_label_); 5300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (lit->IsTrue() || lit->IsJSObject()) { 531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (true_label_ != fall_through_) __ jmp(true_label_); 5320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (lit->IsString()) { 5330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (String::cast(*lit)->length() == 0) { 534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (false_label_ != fall_through_) __ jmp(false_label_); 5350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (true_label_ != fall_through_) __ jmp(true_label_); 5370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 5380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else if (lit->IsSmi()) { 5390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (Smi::cast(*lit)->value() == 0) { 540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (false_label_ != fall_through_) __ jmp(false_label_); 5410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (true_label_ != fall_through_) __ jmp(true_label_); 5430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 5440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 5450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // For simplicity we always test the accumulator register. 5460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Move(result_register(), lit); 5473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch codegen()->DoTest(this); 548d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 549d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 551d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 5520d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::DropAndPlug(int count, 5530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(count > 0); 5550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Drop(count); 5560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 557e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 558e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 5590d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::DropAndPlug( 5600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen int count, 5610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(count > 0); 5630d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Drop(count); 5640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Move(result_register(), reg); 5650d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 566e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 5670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5680d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::DropAndPlug(int count, 5690d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(count > 0); 5710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (count > 1) __ Drop(count - 1); 572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rsp, 0), reg); 573f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 574f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 575f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 5760d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::DropAndPlug(int count, 5770d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Register reg) const { 578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(count > 0); 5790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // For simplicity we always test the accumulator register. 5800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Drop(count); 5810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ Move(result_register(), reg); 5823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), false, NULL, NULL); 5833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch codegen()->DoTest(this); 5840d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 585e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 586e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 5870d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(Label* materialize_true, 5880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(materialize_true == materialize_false); 5900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 5910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 592e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 5930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 5940d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug( 5950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_true, 5960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 5980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 59944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Move(result_register(), isolate()->factory()->true_value()); 600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 6010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_false); 60244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Move(result_register(), isolate()->factory()->false_value()); 6030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&done); 604d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 605d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 606d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 6070d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug( 6080d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_true, 6090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 6110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_true); 61244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Push(isolate()->factory()->true_value()); 613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 6140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(materialize_false); 61544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Push(isolate()->factory()->false_value()); 6160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ bind(&done); 6170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 6180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6200d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(Label* materialize_true, 6210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Label* materialize_false) const { 622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(materialize_true == true_label_); 623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(materialize_false == false_label_); 6240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 6250d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6270d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::EffectContext::Plug(bool flag) const { 6280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 6290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6310d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::AccumulatorValueContext::Plug(bool flag) const { 6320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex value_root_index = 6330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 6340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ LoadRoot(result_register(), value_root_index); 6350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 6360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6380d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::StackValueContext::Plug(bool flag) const { 6390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Heap::RootListIndex value_root_index = 6400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 6410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen __ PushRoot(value_root_index); 6420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 6430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 6450d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::TestContext::Plug(bool flag) const { 6463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch codegen()->PrepareForBailoutBeforeSplit(condition(), 647086aeeaae12517475c22695a200be45495516549Ben Murdoch true, 648086aeeaae12517475c22695a200be45495516549Ben Murdoch true_label_, 649086aeeaae12517475c22695a200be45495516549Ben Murdoch false_label_); 6500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (flag) { 6510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (true_label_ != fall_through_) __ jmp(true_label_); 6520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } else { 6530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (false_label_ != fall_through_) __ jmp(false_label_); 654f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 655f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 656f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 657f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 6583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::DoTest(Expression* condition, 6593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label* if_true, 66080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false, 66180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through) { 662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); 663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, condition->test_id()); 664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testp(result_register(), result_register()); 66580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // The stub returns nonzero for true. 66680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(not_zero, if_true, if_false, fall_through); 66780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 668e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 669e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 67080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid FullCodeGenerator::Split(Condition cc, 67180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true, 67280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false, 67380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through) { 67480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (if_false == fall_through) { 67580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(cc, if_true); 67680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else if (if_true == fall_through) { 67780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(NegateCondition(cc), if_false); 67880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 67980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(cc, if_true); 68080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(if_false); 681e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 682e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 683e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 684e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 685589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::StackOperand(Variable* var) { 686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackAllocated()); 687589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Offset is negative because higher indexes are at lower addresses. 688589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int offset = -var->index() * kPointerSize; 689589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Adjust by a (parameter or local) base offset. 690589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsParameter()) { 691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch offset += kFPOnStackSize + kPCOnStackSize + 692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (info_->scope()->num_parameters() - 1) * kPointerSize; 693589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 694589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch offset += JavaScriptFrameConstants::kLocal0Offset; 695d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 696589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return Operand(rbp, offset); 697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 699d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 700589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) { 701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsContextSlot() || var->IsStackAllocated()); 702589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 703589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int context_chain_length = scope()->ContextChainLength(var->scope()); 704589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ LoadContext(scratch, context_chain_length); 705589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return ContextOperand(scratch, var->index()); 706589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 707589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return StackOperand(var); 708589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 709e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 710d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 711e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 712589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::GetVar(Register dest, Variable* var) { 713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsContextSlot() || var->IsStackAllocated()); 714589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch MemOperand location = VarOperand(var, dest); 715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(dest, location); 716589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch} 717589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 718589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 719589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid FullCodeGenerator::SetVar(Variable* var, 720589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register src, 721589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register scratch0, 722589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Register scratch1) { 723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsContextSlot() || var->IsStackAllocated()); 724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch0.is(src)); 725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch0.is(scratch1)); 726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch1.is(src)); 727589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch MemOperand location = VarOperand(var, scratch0); 728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(location, src); 7293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 730e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Emit the write barrier code if the location is in the heap. 731589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 732589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int offset = Context::SlotOffset(var->index()); 7333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs); 734e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 735d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 736d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 737d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 7383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr, 739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool should_normalize, 740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* if_true, 741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label* if_false) { 742086aeeaae12517475c22695a200be45495516549Ben Murdoch // Only prepare for bailouts before splits if we're in a test 743086aeeaae12517475c22695a200be45495516549Ben Murdoch // context. Otherwise, we let the Visit function deal with the 744086aeeaae12517475c22695a200be45495516549Ben Murdoch // preparation to avoid preparing with the same AST id twice. 745086aeeaae12517475c22695a200be45495516549Ben Murdoch if (!context()->IsTest() || !info_->IsOptimizable()) return; 746086aeeaae12517475c22695a200be45495516549Ben Murdoch 747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label skip; 748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (should_normalize) __ jmp(&skip, Label::kNear); 7493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailout(expr, TOS_REG); 750086aeeaae12517475c22695a200be45495516549Ben Murdoch if (should_normalize) { 751086aeeaae12517475c22695a200be45495516549Ben Murdoch __ CompareRoot(rax, Heap::kTrueValueRootIndex); 752086aeeaae12517475c22695a200be45495516549Ben Murdoch Split(equal, if_true, if_false, NULL); 753086aeeaae12517475c22695a200be45495516549Ben Murdoch __ bind(&skip); 754086aeeaae12517475c22695a200be45495516549Ben Murdoch } 755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) { 759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The variable in the declaration always resides in the current context. 760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0, scope()->ContextChainLength(variable->scope())); 761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (generate_debug_code_) { 762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that we're not inside a with or catch context. 763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, FieldOperand(rsi, HeapObject::kMapOffset)); 764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(rbx, Heap::kWithContextMapRootIndex); 765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(not_equal, kDeclarationInWithContext); 766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(rbx, Heap::kCatchContextMapRootIndex); 767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(not_equal, kDeclarationInCatchContext); 768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitVariableDeclaration( 773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableDeclaration* declaration) { 774589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // If it was not possible to allocate the variable at compile time, we 775589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // need to "declare" it at runtime to make sure it actually exists in the 776589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // local context. 777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableProxy* proxy = declaration->proxy(); 778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableMode mode = declaration->mode(); 779589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* variable = proxy->var(); 780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY; 781589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch switch (variable->location()) { 782589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::UNALLOCATED: 783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch globals_->Add(variable->name(), zone()); 784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch globals_->Add(variable->binding_needs_init() 785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? isolate()->factory()->the_hole_value() 786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : isolate()->factory()->undefined_value(), 787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch zone()); 788589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 789589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 790589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::PARAMETER: 791589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOCAL: 792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hole_init) { 793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ VariableDeclaration"); 79469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(StackOperand(variable), kScratchRegister); 796d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 79769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch break; 798d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 799589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::CONTEXT: 800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hole_init) { 801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ VariableDeclaration"); 802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDebugCheckDeclarationContext(variable); 80369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(ContextOperand(rsi, variable->index()), kScratchRegister); 80569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // No write barrier since the hole value is in old space. 806589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch PrepareForBailoutForId(proxy->id(), NO_REGISTERS); 80769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 80869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch break; 809d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 810589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOOKUP: { 811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ VariableDeclaration"); 812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rsi); 81369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Push(variable->name()); 8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Declaration nodes are always introduced in one of four modes. 815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsDeclaredVariableMode(mode)); 8163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PropertyAttributes attr = 817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IsImmutableVariableMode(mode) ? READ_ONLY : NONE; 81869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Push(Smi::FromInt(attr)); 81969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Push initial value, if any. 82069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Note: For variables we must not push an initial value (such as 82169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // 'undefined') because we may have a (legal) redeclaration and we 82269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // must not destroy the current value. 823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (hole_init) { 82469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ PushRoot(Heap::kTheHoleValueRootIndex); 82569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else { 826589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Push(Smi::FromInt(0)); // Indicates no initial value. 82769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kDeclareLookupSlot, 4); 829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitFunctionDeclaration( 836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FunctionDeclaration* declaration) { 837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableProxy* proxy = declaration->proxy(); 838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* variable = proxy->var(); 839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (variable->location()) { 840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::UNALLOCATED: { 841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch globals_->Add(variable->name(), zone()); 842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<SharedFunctionInfo> function = 843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Compiler::BuildFunctionInfo(declaration->fun(), script(), info_); 844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for stack-overflow exception. 845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (function.is_null()) return SetStackOverflow(); 846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch globals_->Add(function, zone()); 84769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch break; 848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::PARAMETER: 851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::LOCAL: { 852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ FunctionDeclaration"); 853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(declaration->fun()); 854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(StackOperand(variable), result_register()); 855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::CONTEXT: { 859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ FunctionDeclaration"); 860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDebugCheckDeclarationContext(variable); 861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(declaration->fun()); 862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(ContextOperand(rsi, variable->index()), result_register()); 863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = Context::SlotOffset(variable->index()); 864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We know that we have written a function, which is not a smi. 865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteContextSlot(rsi, 866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch offset, 867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch result_register(), 868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch rcx, 869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kDontSaveFPRegs, 870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EMIT_REMEMBERED_SET, 871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OMIT_SMI_CHECK); 872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(proxy->id(), NO_REGISTERS); 873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::LOOKUP: { 877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ FunctionDeclaration"); 878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rsi); 879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(variable->name()); 880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Smi::FromInt(NONE)); 881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(declaration->fun()); 882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kDeclareLookupSlot, 4); 883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) { 890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* variable = declaration->proxy()->var(); 891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(variable->location() == Variable::CONTEXT); 892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(variable->interface()->IsFrozen()); 893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ ModuleDeclaration"); 895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDebugCheckDeclarationContext(variable); 896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load instance object. 898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadContext(rax, scope_->ContextChainLength(scope_->GlobalScope())); 899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, ContextOperand(rax, variable->interface()->Index())); 900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, ContextOperand(rax, Context::EXTENSION_INDEX)); 901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Assign it. 903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(ContextOperand(rsi, variable->index()), rax); 904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We know that we have written a module, which is not a smi. 905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteContextSlot(rsi, 906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Context::SlotOffset(variable->index()), 907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch rax, 908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch rcx, 909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kDontSaveFPRegs, 910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EMIT_REMEMBERED_SET, 911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch OMIT_SMI_CHECK); 912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(declaration->proxy()->id(), NO_REGISTERS); 913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Traverse into body. 915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Visit(declaration->module()); 916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitImportDeclaration(ImportDeclaration* declaration) { 920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableProxy* proxy = declaration->proxy(); 921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* variable = proxy->var(); 922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (variable->location()) { 923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::UNALLOCATED: 924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(rossberg) 925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::CONTEXT: { 928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ ImportDeclaration"); 929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDebugCheckDeclarationContext(variable); 930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(rossberg) 931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::PARAMETER: 935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::LOCAL: 936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Variable::LOOKUP: 937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 938d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 939d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 940d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 941d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitExportDeclaration(ExportDeclaration* declaration) { 943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(rossberg) 944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 947d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 9483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Call the runtime to declare the globals. 949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rsi); // The context is the first argument. 9503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(pairs); 951589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Push(Smi::FromInt(DeclareGlobalsFlags())); 952589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CallRuntime(Runtime::kDeclareGlobals, 3); 9533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Return value is ignored. 9543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 9553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 9563ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) { 958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the runtime to declare the modules. 959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(descriptions); 960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kDeclareModules, 1); 961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return value is ignored. 962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 965f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 966f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ SwitchStatement"); 967f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Breakable nested_statement(this, stmt); 968f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetStatementPosition(stmt); 969086aeeaae12517475c22695a200be45495516549Ben Murdoch 970f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Keep the switch value on the stack until a case matches. 9710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(stmt->tag()); 972086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); 973f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 974f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<CaseClause*>* clauses = stmt->cases(); 975f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* default_clause = NULL; // Can occur anywhere in the list. 976f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 977f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label next_test; // Recycled for each test. 978f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile all the tests with branches to their bodies. 979f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < clauses->length(); i++) { 980f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* clause = clauses->at(i); 9818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch clause->body_target()->Unuse(); 9821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 983f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // The default is not a test, but remember it as final fall through. 984f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (clause->is_default()) { 985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke default_clause = clause; 986f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke continue; 987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ Case comparison"); 990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&next_test); 991f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke next_test.Unuse(); 992f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 993f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile the label expression. 9940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(clause->label()); 995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 99680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Perform the comparison as if via '==='. 997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, Operand(rsp, 0)); // Switch value. 9980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT); 9991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block JumpPatchSite patch_site(masm_); 10000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (inline_smi_code) { 1001257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label slow_case; 1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, rdx); 1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ orp(rcx, rax); 1004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear); 10051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rdx, rax); 100780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(not_equal, &next_test); 100880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Drop(1); // Switch value is no longer needed. 10098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ jmp(clause->body_target()); 101080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&slow_case); 101180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 1012f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 10131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Record position before stub call for type feedback. 10141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block SetSourcePosition(clause->position()); 1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = 1016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code(); 1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, clause->CompareId()); 10183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 10191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label skip; 1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&skip, Label::kNear); 1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailout(clause, TOS_REG); 1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(rax, Heap::kTrueValueRootIndex); 1024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &next_test); 1025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(1); 1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(clause->body_target()); 1027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&skip); 1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testp(rax, rax); 1030f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &next_test); 1031f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(1); // Switch value is no longer needed. 10328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ jmp(clause->body_target()); 1033f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1034f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1035f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Discard the test value and jump to the default if present, otherwise to 1036f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // the end of the statement. 1037f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&next_test); 1038f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Drop(1); // Switch value is no longer needed. 1039f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (default_clause == NULL) { 104069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ jmp(nested_statement.break_label()); 1041f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 10428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ jmp(default_clause->body_target()); 1043f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1044f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1045f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Compile all the case bodies. 1046f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < clauses->length(); i++) { 1047f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ Case body"); 1048f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke CaseClause* clause = clauses->at(i); 10498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ bind(clause->body_target()); 105044f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS); 1051f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke VisitStatements(clause->statements()); 1052f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1053f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 105469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(nested_statement.break_label()); 1055086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 1056f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1057f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1058f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1059f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { 1060f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ ForInStatement"); 1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int slot = stmt->ForInFeedbackSlot(); 1062f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SetStatementPosition(stmt); 1063f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1064f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label loop, exit; 1065f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ForIn loop_statement(this, stmt); 1066f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke increment_loop_depth(); 1067f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the object to enumerate over. If the object is null or undefined, skip 1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // over the loop. See ECMA-262 version 5, section 12.6.4. 10700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(stmt->enumerable()); 1071f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 1072f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, &exit); 1073e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Register null_value = rdi; 1074e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ LoadRoot(null_value, Heap::kNullValueRootIndex); 1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rax, null_value); 1076f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, &exit); 1077f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 10783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutForId(stmt->PrepareId(), TOS_REG); 10793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1080f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Convert the object to a JS object. 1081f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label convert, done_convert; 1082f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, &convert); 10833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx); 1084f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(above_equal, &done_convert); 1085f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&convert); 1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); 1087f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); 1088f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done_convert); 1089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); 1090f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 10913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for proxies. 10923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label call_runtime; 10933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 10943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpObjectType(rax, LAST_JS_PROXY_TYPE, rcx); 10953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(below_equal, &call_runtime); 10963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1097e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Check cache validity in generated code. This is a fast case for 1098e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // the JSObject::IsSimpleEnum cache validity checks. If we cannot 1099e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // guarantee cache validity, call the runtime system to check cache 1100e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // validity or get the property names in a fixed array. 11013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckEnumCache(null_value, &call_runtime); 1102e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1103e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The enum cache is valid. Load the map of the object being 1104e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // iterated over and use the cache for the iteration. 1105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label use_cache; 1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset)); 1107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&use_cache, Label::kNear); 1108f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1109f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the set of properties to enumerate. 1110e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&call_runtime); 1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); // Duplicate the enumerable object on the stack. 1112f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kGetPropertyNamesFast, 1); 1113f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1114f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If we got a map from the runtime call, we can do a fast 1115f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // modification check. Otherwise, we got a fixed array, and we have 1116f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // to do a slow check. 1117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label fixed_array; 1118f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), 1119f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Heap::kMetaMapRootIndex); 1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &fixed_array); 1121f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1122f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // We got a map in register rax. Get the enumeration cache from it. 1123e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ bind(&use_cache); 1124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label no_descriptors; 1126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ EnumLength(rdx, rax); 1128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(rdx, Smi::FromInt(0)); 1129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &no_descriptors); 1130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadInstanceDescriptors(rax, rcx); 1132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, FieldOperand(rcx, DescriptorArray::kEnumCacheOffset)); 1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, FieldOperand(rcx, DescriptorArray::kEnumCacheBridgeCacheOffset)); 1134f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 11353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the four remaining stack slots. 1136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); // Map. 1137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rcx); // Enumeration cache. 1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdx); // Number of valid entries for the map in the enum cache. 1139f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(Smi::FromInt(0)); // Initial index. 1140f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&loop); 1141f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&no_descriptors); 1143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(rsp, Immediate(kPointerSize)); 1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&exit); 1145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // We got a fixed array in register rax. Iterate through that. 11473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label non_proxy; 1148f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&fixed_array); 11493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // No need for a write barrier, we are storing a Smi in the feedback vector. 1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rbx, FeedbackVector()); 1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(FieldOperand(rbx, FixedArray::OffsetOfElementAt(slot)), 1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TypeFeedbackVector::MegamorphicSentinel(isolate())); 11543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(rbx, Smi::FromInt(1)); // Smi indicates slow check 1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, Operand(rsp, 0 * kPointerSize)); // Get enumerated object 11563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 11573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpObjectType(rcx, LAST_JS_PROXY_TYPE, rcx); 11583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above, &non_proxy); 11593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(rbx, Smi::FromInt(0)); // Zero indicates proxy 11603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&non_proxy); 1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rbx); // Smi 1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); // Array 1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, FieldOperand(rax, FixedArray::kLengthOffset)); 1164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); // Fixed array length (as smi). 1165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(Smi::FromInt(0)); // Initial index. 1166f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for doing the condition check. 11683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); 1169f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&loop); 1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, Operand(rsp, 0 * kPointerSize)); // Get the current index. 1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rax, Operand(rsp, 1 * kPointerSize)); // Compare to the array length. 117269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(above_equal, loop_statement.break_label()); 1173f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1174f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the current entry of the array into register rbx. 1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, Operand(rsp, 2 * kPointerSize)); 1176f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch SmiIndex index = masm()->SmiToIndex(rax, rax, kPointerSizeLog2); 1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, FieldOperand(rbx, 1178f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke index.reg, 1179f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke index.scale, 1180f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FixedArray::kHeaderSize)); 1181f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 11823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the expected map from the stack or a smi in the 1183f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // permanent slow case into register rdx. 1184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, Operand(rsp, 3 * kPointerSize)); 1185f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1186f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the expected map still matches that of the enumerable. 11873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If not, we may have to filter the key. 1188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label update_each; 1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, Operand(rsp, 4 * kPointerSize)); 1190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rdx, FieldOperand(rcx, HeapObject::kMapOffset)); 1191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &update_each, Label::kNear); 1192f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 11933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // For proxies, no filtering is done. 11943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // TODO(rossberg): What if only a prototype is a proxy? Not specified yet. 11953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(rdx, Smi::FromInt(0)); 11963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, &update_each, Label::kNear); 11973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1198f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Convert the entry to a string or null if it isn't a property 1199f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // anymore. If the property has been removed while iterating, we 1200f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // just skip it. 1201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rcx); // Enumerable. 1202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rbx); // Current entry. 1203f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); 120444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Cmp(rax, Smi::FromInt(0)); 120569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ j(equal, loop_statement.continue_label()); 1206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, rax); 1207f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1208f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Update the 'each' property or variable from the possibly filtered 1209f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // entry in register rbx. 1210f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&update_each); 1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(result_register(), rbx); 1212f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment as if via '='. 1213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { EffectContext context(this); 12143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitAssignment(stmt->each()); 1215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1216f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1217f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for the body of the loop. 1218f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Visit(stmt->body()); 1219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1220f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Generate code for going to the next element by incrementing the 1221f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // index (smi) stored on top of the stack. 122269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(loop_statement.continue_label()); 1223f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1)); 1224f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBackEdgeBookkeeping(stmt, &loop); 1226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ jmp(&loop); 1227f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1228f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Remove the pointers stored on the stack. 122969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(loop_statement.break_label()); 1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(rsp, Immediate(5 * kPointerSize)); 1231f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1232f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Exit and decrement the loop depth. 12333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 1234f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&exit); 1235f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke decrement_loop_depth(); 1236f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 12373ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 12383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { 1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ ForOfStatement"); 1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetStatementPosition(stmt); 1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Iteration loop_statement(this, stmt); 1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch increment_loop_depth(); 1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // var iterator = iterable[Symbol.iterator](); 1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForEffect(stmt->assign_iterator()); 1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Loop entry. 1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(loop_statement.continue_label()); 1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // result = iterator.next() 1253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForEffect(stmt->next_result()); 1254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // if (result.done) break; 1256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label result_not_done; 1257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForControl(stmt->result_done(), 1258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch loop_statement.break_label(), 1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &result_not_done, 1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &result_not_done); 1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&result_not_done); 1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // each = result.value 1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForEffect(stmt->assign_each()); 1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Generate code for the body of the loop. 1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Visit(stmt->body()); 1268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check stack before looping. 1270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS); 1271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label()); 1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(loop_statement.continue_label()); 1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Exit and decrement the loop depth. 1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(loop_statement.break_label()); 1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch decrement_loop_depth(); 1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 12818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangvoid FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info, 12828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang bool pretenure) { 1283f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Use the fast case closure allocation code that allocates in new 1284e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // space for nested functions that don't need literals cloning. If 1285e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // we're running with the --always-opt or the --prepare-always-opt 1286e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // flag, we need to use the runtime function so that the new function 1287e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // we are creating here gets a chance to have its code optimized and 1288e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // doesn't just get a copy of the existing unoptimized code. 1289e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!FLAG_always_opt && 1290e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch !FLAG_prepare_always_opt && 129144f0eee88ff00398ff7f715fab053374d808c90dSteve Block !pretenure && 1292e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch scope()->is_function_scope() && 129344f0eee88ff00398ff7f715fab053374d808c90dSteve Block info->num_literals() == 0) { 1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind()); 1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rbx, info); 1296f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 1297f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rsi); 1299f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ Push(info); 130044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Push(pretenure 130144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? isolate()->factory()->true_value() 130244f0eee88ff00398ff7f715fab053374d808c90dSteve Block : isolate()->factory()->false_value()); 13038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ CallRuntime(Runtime::kNewClosure, 3); 1304f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 13050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 13063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 13073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 13083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1309d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 13103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ VariableProxy"); 13113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch EmitVariableLoad(expr); 1312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 1313e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) { 1316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cnmt(masm_, "[ SuperReference "); 1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(LoadDescriptor::ReceiverRegister(), 1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol()); 1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(LoadDescriptor::NameRegister(), home_object_symbol); 1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId()); 1325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(rax, isolate()->factory()->undefined_value()); 1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &done); 1329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kThrowNonMethodError, 0); 1330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 1331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, 1335589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch TypeofState typeof_state, 1336589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label* slow) { 133759151504615d929945dc59db37bf1166937748c6Steve Block Register context = rsi; 133859151504615d929945dc59db37bf1166937748c6Steve Block Register temp = rdx; 133959151504615d929945dc59db37bf1166937748c6Steve Block 134059151504615d929945dc59db37bf1166937748c6Steve Block Scope* s = scope(); 134159151504615d929945dc59db37bf1166937748c6Steve Block while (s != NULL) { 134259151504615d929945dc59db37bf1166937748c6Steve Block if (s->num_heap_slots() > 0) { 1343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (s->calls_sloppy_eval()) { 134459151504615d929945dc59db37bf1166937748c6Steve Block // Check that extension is NULL. 1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(ContextOperand(context, Context::EXTENSION_INDEX), 134659151504615d929945dc59db37bf1166937748c6Steve Block Immediate(0)); 134759151504615d929945dc59db37bf1166937748c6Steve Block __ j(not_equal, slow); 134859151504615d929945dc59db37bf1166937748c6Steve Block } 134959151504615d929945dc59db37bf1166937748c6Steve Block // Load next context in chain. 1350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); 135159151504615d929945dc59db37bf1166937748c6Steve Block // Walk the rest of the chain without clobbering rsi. 135259151504615d929945dc59db37bf1166937748c6Steve Block context = temp; 135359151504615d929945dc59db37bf1166937748c6Steve Block } 135459151504615d929945dc59db37bf1166937748c6Steve Block // If no outer scope calls eval, we do not need to check more 135559151504615d929945dc59db37bf1166937748c6Steve Block // context extensions. If we have reached an eval scope, we check 135659151504615d929945dc59db37bf1166937748c6Steve Block // all extensions from this point. 1357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope()) break; 135859151504615d929945dc59db37bf1166937748c6Steve Block s = s->outer_scope(); 135959151504615d929945dc59db37bf1166937748c6Steve Block } 136059151504615d929945dc59db37bf1166937748c6Steve Block 136159151504615d929945dc59db37bf1166937748c6Steve Block if (s != NULL && s->is_eval_scope()) { 136259151504615d929945dc59db37bf1166937748c6Steve Block // Loop up the context chain. There is no frame effect so it is 136359151504615d929945dc59db37bf1166937748c6Steve Block // safe to use raw labels here. 1364257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label next, fast; 136559151504615d929945dc59db37bf1166937748c6Steve Block if (!context.is(temp)) { 1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(temp, context); 136759151504615d929945dc59db37bf1166937748c6Steve Block } 136859151504615d929945dc59db37bf1166937748c6Steve Block // Load map for comparison into register, outside loop. 1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(kScratchRegister, Heap::kNativeContextMapRootIndex); 137059151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&next); 1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Terminate at native context. 1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(kScratchRegister, FieldOperand(temp, HeapObject::kMapOffset)); 1373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &fast, Label::kNear); 137459151504615d929945dc59db37bf1166937748c6Steve Block // Check that extension is NULL. 1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(ContextOperand(temp, Context::EXTENSION_INDEX), Immediate(0)); 137659151504615d929945dc59db37bf1166937748c6Steve Block __ j(not_equal, slow); 137759151504615d929945dc59db37bf1166937748c6Steve Block // Load next context in chain. 1378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(temp, ContextOperand(temp, Context::PREVIOUS_INDEX)); 137959151504615d929945dc59db37bf1166937748c6Steve Block __ jmp(&next); 138059151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&fast); 138159151504615d929945dc59db37bf1166937748c6Steve Block } 138259151504615d929945dc59db37bf1166937748c6Steve Block 138359151504615d929945dc59db37bf1166937748c6Steve Block // All extension objects were empty and it is safe to use a global 138459151504615d929945dc59db37bf1166937748c6Steve Block // load IC call. 1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); 1386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(LoadDescriptor::NameRegister(), proxy->var()->name()); 1387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 1388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(VectorLoadICDescriptor::SlotRegister(), 1389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(proxy->VariableFeedbackSlot())); 1390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ContextualMode mode = (typeof_state == INSIDE_TYPEOF) 1393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? NOT_CONTEXTUAL 1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : CONTEXTUAL; 1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(mode); 139659151504615d929945dc59db37bf1166937748c6Steve Block} 139759151504615d929945dc59db37bf1166937748c6Steve Block 139859151504615d929945dc59db37bf1166937748c6Steve Block 1399589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben MurdochMemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, 1400589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label* slow) { 1401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsContextSlot()); 140259151504615d929945dc59db37bf1166937748c6Steve Block Register context = rsi; 140359151504615d929945dc59db37bf1166937748c6Steve Block Register temp = rbx; 140459151504615d929945dc59db37bf1166937748c6Steve Block 1405589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { 140659151504615d929945dc59db37bf1166937748c6Steve Block if (s->num_heap_slots() > 0) { 1407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (s->calls_sloppy_eval()) { 140859151504615d929945dc59db37bf1166937748c6Steve Block // Check that extension is NULL. 1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(ContextOperand(context, Context::EXTENSION_INDEX), 141059151504615d929945dc59db37bf1166937748c6Steve Block Immediate(0)); 141159151504615d929945dc59db37bf1166937748c6Steve Block __ j(not_equal, slow); 141259151504615d929945dc59db37bf1166937748c6Steve Block } 1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); 141459151504615d929945dc59db37bf1166937748c6Steve Block // Walk the rest of the chain without clobbering rsi. 141559151504615d929945dc59db37bf1166937748c6Steve Block context = temp; 141659151504615d929945dc59db37bf1166937748c6Steve Block } 141759151504615d929945dc59db37bf1166937748c6Steve Block } 141859151504615d929945dc59db37bf1166937748c6Steve Block // Check that last extension is NULL. 1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(ContextOperand(context, Context::EXTENSION_INDEX), Immediate(0)); 142059151504615d929945dc59db37bf1166937748c6Steve Block __ j(not_equal, slow); 1421e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1422e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // This function is used only for loads, not stores, so it's safe to 1423e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // return an rsi-based operand (the write barrier cannot be allowed to 1424e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // destroy the rsi register). 1425589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return ContextOperand(context, var->index()); 142659151504615d929945dc59db37bf1166937748c6Steve Block} 142759151504615d929945dc59db37bf1166937748c6Steve Block 142859151504615d929945dc59db37bf1166937748c6Steve Block 1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy, 1430589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch TypeofState typeof_state, 1431589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label* slow, 1432589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label* done) { 143359151504615d929945dc59db37bf1166937748c6Steve Block // Generate fast-case code for variables that might be shadowed by 143459151504615d929945dc59db37bf1166937748c6Steve Block // eval-introduced variables. Eval is used a lot without 143559151504615d929945dc59db37bf1166937748c6Steve Block // introducing variables. In those cases, we do not want to 143659151504615d929945dc59db37bf1166937748c6Steve Block // perform a runtime call for all variables in the scope 143759151504615d929945dc59db37bf1166937748c6Steve Block // containing the eval. 1438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* var = proxy->var(); 14393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (var->mode() == DYNAMIC_GLOBAL) { 1440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitLoadGlobalCheckExtensions(proxy, typeof_state, slow); 144159151504615d929945dc59db37bf1166937748c6Steve Block __ jmp(done); 14423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (var->mode() == DYNAMIC_LOCAL) { 1443589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* local = var->local_if_not_shadowed(); 1444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, ContextSlotOperandCheckExtensions(local, slow)); 1445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (local->mode() == LET || local->mode() == CONST || 1446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch local->mode() == CONST_LEGACY) { 1447589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 1448589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ j(not_equal, done); 1449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (local->mode() == CONST_LEGACY) { 14503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { // LET || CONST 14523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(var->name()); 14533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kThrowReferenceError, 1); 14543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 145559151504615d929945dc59db37bf1166937748c6Steve Block } 1456589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ jmp(done); 145759151504615d929945dc59db37bf1166937748c6Steve Block } 145859151504615d929945dc59db37bf1166937748c6Steve Block} 145959151504615d929945dc59db37bf1166937748c6Steve Block 146059151504615d929945dc59db37bf1166937748c6Steve Block 14613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { 14623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Record position before possible IC call. 14633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SetSourcePosition(proxy->position()); 14643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Variable* var = proxy->var(); 14653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1466589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Three cases: global variables, lookup variables, and all other types of 1467589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // variables. 1468589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch switch (var->location()) { 1469589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::UNALLOCATED: { 1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Global variable"); 1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(LoadDescriptor::NameRegister(), var->name()); 1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); 1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(VectorLoadICDescriptor::SlotRegister(), 1475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(proxy->VariableFeedbackSlot())); 1476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(CONTEXTUAL); 1478589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch context()->Plug(rax); 1479589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 1480589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 148159151504615d929945dc59db37bf1166937748c6Steve Block 1482589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::PARAMETER: 1483589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOCAL: 1484589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::CONTEXT: { 1485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, var->IsContextSlot() ? "[ Context slot" 1486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : "[ Stack slot"); 14873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (var->binding_needs_init()) { 14883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // var->scope() may be NULL when the proxy is located in eval code and 14893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // refers to a potential outside binding. Currently those bindings are 14903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // always looked up dynamically, i.e. in that case 14913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // var->location() == LOOKUP. 14923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // always holds. 1493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->scope() != NULL); 14943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if the binding really needs an initialization check. The check 14963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // can be skipped in the following situation: we have a LET or CONST 14973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // binding in harmony mode, both the Variable and the VariableProxy have 14983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the same declaration scope (i.e. they are both in global code, in the 14993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // same function or in the same eval code) and the VariableProxy is in 15003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the source physically located after the initializer of the variable. 15013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 15023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We cannot skip any initialization checks for CONST in non-harmony 15033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // mode because const variables may be declared but never initialized: 15043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // if (false) { const x; }; var y = x; 15053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 15063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The condition on the declaration scopes is a conservative check for 15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // nested functions that access a binding and are called before the 15083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // binding is initialized: 15093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // function() { f(); let x = 1; function f() { x = 2; } } 15103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 15113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool skip_init_check; 15123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) { 15133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch skip_init_check = false; 15143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 15153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that we always have valid source position. 1516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->initializer_position() != RelocInfo::kNoPosition); 1517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(proxy->position() != RelocInfo::kNoPosition); 1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch skip_init_check = var->mode() != CONST_LEGACY && 15193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch var->initializer_position() < proxy->position(); 15203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 15213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!skip_init_check) { 15233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Let and const need a read barrier. 15243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label done; 15253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GetVar(rax, var); 15263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 15273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &done, Label::kNear); 1528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->mode() == LET || var->mode() == CONST) { 15293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Throw a reference error when using an uninitialized let/const 15303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // binding in harmony mode. 15313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(var->name()); 15323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kThrowReferenceError, 1); 15333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 15343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Uninitalized const bindings outside of harmony mode are unholed. 1535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->mode() == CONST_LEGACY); 15363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 15373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 15383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(rax); 15403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 1541589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 1542589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 15433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(var); 1544589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 1545589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 1546d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1547589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOOKUP: { 1548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Lookup slot"); 1549589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label done, slow; 1550589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Generate code for loading from variables potentially shadowed 1551589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // by eval-introduced variables. 1552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done); 1553589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ bind(&slow); 1554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rsi); // Context. 155569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Push(var->name()); 1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kLoadLookupSlot, 2); 155769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ bind(&done); 155869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch context()->Plug(rax); 1559589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 1560f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 15613ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 15623ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 15633ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 15643ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1565d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 1566d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ RegExpLiteral"); 1567bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Label materialized; 15683ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Registers will be used as follows: 15693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // rdi = JS function. 1570bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // rcx = literals array. 1571bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // rbx = regexp literal. 1572bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // rax = regexp literal clone. 1573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, FieldOperand(rdi, JSFunction::kLiteralsOffset)); 15753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block int literal_offset = 157680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen FixedArray::kHeaderSize + expr->literal_index() * kPointerSize; 1577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, FieldOperand(rcx, literal_offset)); 1578bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); 1579589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ j(not_equal, &materialized, Label::kNear); 1580bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 15813ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Create regexp literal using runtime function 15823ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Result will be in rax. 1583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rcx); 15843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(Smi::FromInt(expr->literal_index())); 15853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(expr->pattern()); 15863ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ Push(expr->flags()); 15873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 1588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, rax); 1589bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 1590bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&materialized); 1591bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; 1592bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch Label allocated, runtime_allocate; 1593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Allocate(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT); 1594bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ jmp(&allocated); 1595bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 1596bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&runtime_allocate); 1597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rbx); 1598bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ Push(Smi::FromInt(size)); 1599bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ CallRuntime(Runtime::kAllocateInNewSpace, 1); 1600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rbx); 1601bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 1602bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch __ bind(&allocated); 1603bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // Copy the content into the newly allocated memory. 1604bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch // (Unroll copy loop once for better throughput). 1605bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { 1606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, FieldOperand(rbx, i)); 1607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, FieldOperand(rbx, i + kPointerSize)); 1608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rax, i), rdx); 1609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rax, i + kPointerSize), rcx); 1610bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 1611bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch if ((size % (2 * kPointerSize)) != 0) { 1612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, FieldOperand(rbx, size - kPointerSize)); 1613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rax, size - kPointerSize), rdx); 1614bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch } 16150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 1616d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1617d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1618d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 16193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitAccessor(Expression* expression) { 16203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (expression == NULL) { 16213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PushRoot(Heap::kNullValueRootIndex); 16223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 16233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForStackValue(expression); 16243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 16253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 16263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 16273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1628d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 1629d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ ObjectLiteral"); 1630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch expr->BuildConstantProperties(isolate()); 16323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedArray> constant_properties = expr->constant_properties(); 163344f0eee88ff00398ff7f715fab053374d808c90dSteve Block int flags = expr->fast_elements() 163444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? ObjectLiteral::kFastElements 163544f0eee88ff00398ff7f715fab053374d808c90dSteve Block : ObjectLiteral::kNoFlags; 163644f0eee88ff00398ff7f715fab053374d808c90dSteve Block flags |= expr->has_function() 163744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? ObjectLiteral::kHasFunction 163844f0eee88ff00398ff7f715fab053374d808c90dSteve Block : ObjectLiteral::kNoFlags; 16393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int properties_count = constant_properties->length() / 2; 1640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->may_store_doubles() || expr->depth() > 1 || 1641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm()->serializer_enabled() || flags != ObjectLiteral::kFastElements || 16423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { 1643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(FieldOperand(rdi, JSFunction::kLiteralsOffset)); 1645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Smi::FromInt(expr->literal_index())); 1646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(constant_properties); 1647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Smi::FromInt(flags)); 1648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kCreateObjectLiteral, 4); 16493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 1650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, FieldOperand(rdi, JSFunction::kLiteralsOffset)); 1652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rbx, Smi::FromInt(expr->literal_index())); 1653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rcx, constant_properties); 1654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rdx, Smi::FromInt(flags)); 1655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FastCloneShallowObjectStub stub(isolate(), properties_count); 16563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallStub(&stub); 1657d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1658d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If result_saved is true the result is on top of the stack. If 1660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // result_saved is false the result is in rax. 1661d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool result_saved = false; 1662d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 16633e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Mark all computed expressions that are bound to a key that 16643e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // is shadowed by a later occurrence of the same key. For the 16653e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // marked expressions, no store code is emitted. 1666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch expr->CalculateEmitStore(zone()); 16673e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 1668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AccessorTable accessor_table(zone()); 1669d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < expr->properties()->length(); i++) { 1670d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ObjectLiteral::Property* property = expr->properties()->at(i); 1671d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (property->IsCompileTimeValue()) continue; 1672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1673d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Literal* key = property->key(); 1674d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* value = property->value(); 1675d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (!result_saved) { 1676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); // Save result on the stack 1677d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result_saved = true; 1678d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1679d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (property->kind()) { 1680e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::CONSTANT: 1681e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke UNREACHABLE(); 1682e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!CompileTimeValue::IsCompileTimeValue(value)); 1684e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Fall through. 1685d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case ObjectLiteral::Property::COMPUTED: 1686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (key->value()->IsInternalizedString()) { 16873e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu if (property->emit_store()) { 1688053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block VisitForAccumulatorValue(value); 1689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(StoreDescriptor::ValueRegister().is(rax)); 1690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(StoreDescriptor::NameRegister(), key->value()); 1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0)); 1692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallStoreIC(key->LiteralFeedbackId()); 1693086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailoutForId(key->id(), NO_REGISTERS); 1694053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block } else { 1695053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block VisitForEffect(value); 16963e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 1697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Operand(rsp, 0)); // Duplicate receiver. 17000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(key); 17010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(value); 17023e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu if (property->emit_store()) { 1703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Smi::FromInt(SLOPPY)); // Strict mode 1704e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CallRuntime(Runtime::kSetProperty, 4); 17053e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } else { 17063e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ Drop(3); 17073e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 1708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ObjectLiteral::Property::PROTOTYPE: 1710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Operand(rsp, 0)); // Duplicate receiver. 1711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(value); 1712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (property->emit_store()) { 1713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kSetPrototype, 2); 1714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(2); 1716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 171885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch case ObjectLiteral::Property::GETTER: 17193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch accessor_table.lookup(key)->second->getter = value; 17203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 17213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case ObjectLiteral::Property::SETTER: 17223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch accessor_table.lookup(key)->second->setter = value; 1723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 1724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1725d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 1726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 17273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Emit code to define accessors, using only a single call to the runtime for 17283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // each pair of corresponding getters and setters. 17293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (AccessorTable::Iterator it = accessor_table.begin(); 17303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch it != accessor_table.end(); 17313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ++it) { 1732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Operand(rsp, 0)); // Duplicate receiver. 17333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForStackValue(it->first); 17343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitAccessor(it->second->getter); 17353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitAccessor(it->second->setter); 17363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(Smi::FromInt(NONE)); 1737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5); 17383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 17393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 174044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (expr->has_function()) { 1741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(result_saved); 1742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Operand(rsp, 0)); 174344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CallRuntime(Runtime::kToFastProperties, 1); 174444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 174544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1746e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 17470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 1748e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 17490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 17503ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 17513ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 17523ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 17533ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1754d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 17553ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ ArrayLiteral"); 1756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch expr->BuildConstantElements(isolate()); 1758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int flags = expr->depth() == 1 1759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ? ArrayLiteral::kShallowElements 1760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : ArrayLiteral::kNoFlags; 1761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1762f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<Expression*>* subexprs = expr->values(); 1763f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int length = subexprs->length(); 17643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedArray> constant_elements = expr->constant_elements(); 1765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(2, constant_elements->length()); 17663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind constant_elements_kind = 17673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); 1768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool has_constant_fast_elements = 1769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IsFastObjectElementsKind(constant_elements_kind); 17703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedArrayBase> constant_elements_values( 17713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArrayBase::cast(constant_elements->get(1))); 1772f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE; 1774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) { 1775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the only customer of allocation sites is transitioning, then 1776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // we can turn it off if we don't have anywhere else to transition to. 1777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; 1778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->depth() > 1 || length > JSObject::kInitialMaxFastElementArray) { 1781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(FieldOperand(rbx, JSFunction::kLiteralsOffset)); 1783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Smi::FromInt(expr->literal_index())); 1784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(constant_elements); 1785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Smi::FromInt(flags)); 1786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kCreateArrayLiteral, 4); 1787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 1788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, FieldOperand(rbx, JSFunction::kLiteralsOffset)); 1790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rbx, Smi::FromInt(expr->literal_index())); 1791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rcx, constant_elements); 1792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); 1793f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 17943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 17953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 17963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block bool result_saved = false; // Is the result saved to the stack? 17973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 17983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Emit code to evaluate all the non-constant subexpressions and to store 17993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // them into the newly cloned array. 1800f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke for (int i = 0; i < length; i++) { 18013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Expression* subexpr = subexprs->at(i); 18023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // If the subexpression is a literal or a simple materialized literal it 18033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // is already set in the cloned array. 1804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; 18053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 18063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!result_saved) { 1807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); // array literal 1808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Smi::FromInt(expr->literal_index())); 18093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block result_saved = true; 18103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 18110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(subexpr); 18123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (IsFastObjectElementsKind(constant_elements_kind)) { 1814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fast-case array literal with ElementsKind of FAST_*_ELEMENTS, they 1815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // cannot transition and don't need to call the runtime stub. 18163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int offset = FixedArray::kHeaderSize + (i * kPointerSize); 1817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, Operand(rsp, kPointerSize)); // Copy of array literal. 1818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, FieldOperand(rbx, JSObject::kElementsOffset)); 18193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the subexpression value in the array's elements. 1820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rbx, offset), result_register()); 18213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Update the write barrier for the array store. 18223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(rbx, offset, result_register(), rcx, 18233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, 18243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, 18253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch INLINE_SMI_CHECK); 18263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 18273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the subexpression value in the array's elements. 18283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(rcx, Smi::FromInt(i)); 1829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StoreArrayLiteralElementStub stub(isolate()); 18303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallStub(&stub); 18313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1832086aeeaae12517475c22695a200be45495516549Ben Murdoch 1833086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); 18343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 18353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1836e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (result_saved) { 1837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(rsp, Immediate(kPointerSize)); // literal index 18380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 1839e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 18400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 18413ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 18423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 18433ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 18443ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1845402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuvoid FullCodeGenerator::VisitAssignment(Assignment* expr) { 1846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->target()->IsValidReferenceExpression()); 1847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1848402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Comment cmnt(masm_, "[ Assignment"); 1849f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1850402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Left-hand side can only be a property, a global or a (parameter or local) 18513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // slot. 1852402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1853402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu LhsKind assign_type = VARIABLE; 185480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Property* property = expr->target()->AsProperty(); 185580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (property != NULL) { 185680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen assign_type = (property->key()->IsPropertyName()) 185780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ? NAMED_PROPERTY 185880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen : KEYED_PROPERTY; 1859402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1860402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1861402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Evaluate LHS expression. 1862402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1863402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1864402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Nothing to do here. 1865402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1866402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1867402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 1868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We need the receiver both on the stack and in the register. 1869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->obj()); 1870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0)); 1871402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } else { 18720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(property->obj()); 1873402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1874402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1875086aeeaae12517475c22695a200be45495516549Ben Murdoch case KEYED_PROPERTY: { 1876f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (expr->is_compound()) { 18773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(property->obj()); 1878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->key()); 1879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, kPointerSize)); 1880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(LoadDescriptor::NameRegister(), Operand(rsp, 0)); 1881f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 18823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(property->obj()); 18833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(property->key()); 1884f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 1885402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1886086aeeaae12517475c22695a200be45495516549Ben Murdoch } 1887402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1888402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 18898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // For compound assignments we need another deoptimization point after the 18908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // variable/property load. 1891402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu if (expr->is_compound()) { 18920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { AccumulatorValueContext context(this); 18930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen switch (assign_type) { 18940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case VARIABLE: 18953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch EmitVariableLoad(expr->target()->AsVariableProxy()); 18968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PrepareForBailout(expr->target(), TOS_REG); 18970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 18980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case NAMED_PROPERTY: 18990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitNamedPropertyLoad(property); 1900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(property->LoadId(), TOS_REG); 19010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 19020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case KEYED_PROPERTY: 19030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitKeyedPropertyLoad(property); 1904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(property->LoadId(), TOS_REG); 19050d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 19060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 1907402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1908402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 190980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op = expr->binary_op(); 1910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); // Left operand goes on the stack. 1911e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitForAccumulatorValue(expr->value()); 1912402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 191380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen OverwriteMode mode = expr->value()->ResultOverwriteAllowed() 191480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen ? OVERWRITE_RIGHT 191580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen : NO_OVERWRITE; 191680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen SetSourcePosition(expr->position() + 1); 19170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AccumulatorValueContext context(this); 191880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (ShouldInlineSmiCase(op)) { 1919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitInlineSmiBinaryOp(expr->binary_operation(), 192080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen op, 192180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen mode, 192280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen expr->target(), 1923e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch expr->value()); 192480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 1925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch EmitBinaryOp(expr->binary_operation(), op, mode); 192680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 1927086aeeaae12517475c22695a200be45495516549Ben Murdoch // Deoptimization point in case the binary operation may have side effects. 1928086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailout(expr->binary_operation(), TOS_REG); 192980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 19300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->value()); 1931402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1932402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1933402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Record source position before possible IC call. 1934402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu SetSourcePosition(expr->position()); 1935402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1936402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Store the value. 1937402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu switch (assign_type) { 1938402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case VARIABLE: 1939402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), 19400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen expr->op()); 1941086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 1942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(rax); 1943402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1944402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case NAMED_PROPERTY: 1945402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitNamedPropertyAssignment(expr); 1946402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1947402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu case KEYED_PROPERTY: 1948402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu EmitKeyedPropertyAssignment(expr); 1949402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu break; 1950402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu } 1951402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu} 1952402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1953402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 1954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::VisitYield(Yield* expr) { 1955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Yield"); 1956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Evaluate yielded value first; the initial iterator definition depends on 1957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // this. It stays on the stack while we update the iterator. 1958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(expr->expression()); 1959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (expr->yield_kind()) { 1961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Yield::kSuspend: 1962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pop value from top-of-stack slot; box result into result register. 1963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCreateIteratorResult(false); 1964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(result_register()); 1965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fall through. 1966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Yield::kInitial: { 1967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label suspend, continuation, post_runtime, resume; 1968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&suspend); 1970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&continuation); 1972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&resume); 1973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&suspend); 1975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(expr->generator_object()); 1976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos())); 1977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset), 1978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(continuation.pos())); 1979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rax, JSGeneratorObject::kContextOffset), rsi); 1980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, rsi); 1981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteField(rax, JSGeneratorObject::kContextOffset, rcx, rdx, 1982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kDontSaveFPRegs); 1983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(rbx, Operand(rbp, StandardFrameConstants::kExpressionsOffset)); 1984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rsp, rbx); 1985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &post_runtime); 1986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); // generator object 1987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); 1988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(context_register(), 1989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(rbp, StandardFrameConstants::kContextOffset)); 1990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&post_runtime); 1991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(result_register()); 1993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitReturnSequence(); 1994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&resume); 1996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(result_register()); 1997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 1998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Yield::kFinal: { 2001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(expr->generator_object()); 2002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(FieldOperand(result_register(), 2003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSGeneratorObject::kContinuationOffset), 2004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(JSGeneratorObject::kGeneratorClosed)); 2005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pop value from top-of-stack slot, box result into result register. 2006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCreateIteratorResult(true); 2007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitUnwindBeforeReturn(); 2008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitReturnSequence(); 2009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Yield::kDelegating: { 2013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(expr->generator_object()); 2014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Initial stack layout is as follows: 2016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // [sp + 1 * kPointerSize] iter 2017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // [sp + 0 * kPointerSize] g 2018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label l_catch, l_try, l_suspend, l_continuation, l_resume; 2020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label l_next, l_call, l_loop; 2021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register load_receiver = LoadDescriptor::ReceiverRegister(); 2022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register load_name = LoadDescriptor::NameRegister(); 2023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Initial send value is undefined. 2025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 2026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&l_next); 2027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } 2029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&l_catch); 2030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); 2031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(load_name, Heap::kthrow_stringRootIndex); // "throw" 2032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(load_name); 2033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Operand(rsp, 2 * kPointerSize)); // iter 2034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); // exception 2035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&l_call); 2036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // try { received = %yield result } 2038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Shuffle the received result above a try handler and yield it without 2039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // re-boxing. 2040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&l_try); 2041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rax); // result 2042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushTryHandler(StackHandler::CATCH, expr->index()); 2043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int handler_size = StackHandlerConstants::kSize; 2044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); // result 2045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&l_suspend); 2046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&l_continuation); 2047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&l_resume); 2048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&l_suspend); 2049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int generator_object_depth = kPointerSize + handler_size; 2050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, Operand(rsp, generator_object_depth)); 2051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); // g 2052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); 2053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(FieldOperand(rax, JSGeneratorObject::kContinuationOffset), 2054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(l_continuation.pos())); 2055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rax, JSGeneratorObject::kContextOffset), rsi); 2056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, rsi); 2057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteField(rax, JSGeneratorObject::kContextOffset, rcx, rdx, 2058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kDontSaveFPRegs); 2059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); 2060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(context_register(), 2061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(rbp, StandardFrameConstants::kContextOffset)); 2062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rax); // result 2063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitReturnSequence(); 2064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&l_resume); // received in rax 2065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PopTryHandler(); 2066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // receiver = iter; f = 'next'; arg = received; 2068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&l_next); 2069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(load_name, Heap::knext_stringRootIndex); 2071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(load_name); // "next" 2072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Operand(rsp, 2 * kPointerSize)); // iter 2073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); // received 2074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // result = receiver[f](arg); 2076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&l_call); 2077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(load_receiver, Operand(rsp, kPointerSize)); 2078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 2079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(VectorLoadICDescriptor::SlotRegister(), 2080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(expr->KeyedLoadFeedbackSlot())); 2081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code(); 2083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, TypeFeedbackId::None()); 2084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, rax); 2085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rsp, 2 * kPointerSize), rdi); 2086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD); 2087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&stub); 2088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Drop(1); // The function is still on the stack; drop it. 2091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // if (!result.done) goto l_try; 2093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&l_loop); 2094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(load_receiver, rax); 2095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(load_receiver); // save result 2096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done" 2097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 2098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(VectorLoadICDescriptor::SlotRegister(), 2099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(expr->DoneFeedbackSlot())); 2100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(NOT_CONTEXTUAL); // rax=result.done 2102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); 2103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(bool_ic); 2104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testp(result_register(), result_register()); 2105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(zero, &l_try); 2106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // result.value 2108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(load_receiver); // result 2109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(load_name, Heap::kvalue_stringRootIndex); // "value" 2110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 2111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(VectorLoadICDescriptor::SlotRegister(), 2112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(expr->ValueFeedbackSlot())); 2113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(NOT_CONTEXTUAL); // result.value in rax 2115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->DropAndPlug(2, rax); // drop iter and g 2116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 2117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitGeneratorResume(Expression *generator, 2123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression *value, 2124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSGeneratorObject::ResumeMode resume_mode) { 2125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The value stays in rax, and is ultimately read by the resumed generator, as 2126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it 2127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is read to throw the value when the resumed generator is already closed. 2128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rbx will hold the generator object until the activation has been resumed. 2129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(generator); 2130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(value); 2131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rbx); 2132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check generator state. 2134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label wrong_state, closed_state, done; 2135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0); 2136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0); 2137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiCompare(FieldOperand(rbx, JSGeneratorObject::kContinuationOffset), 2138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(0)); 2139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &closed_state); 2140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(less, &wrong_state); 2141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load suspended function and context. 2143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rsi, FieldOperand(rbx, JSGeneratorObject::kContextOffset)); 2144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, FieldOperand(rbx, JSGeneratorObject::kFunctionOffset)); 2145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push receiver. 2147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(FieldOperand(rbx, JSGeneratorObject::kReceiverOffset)); 2148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push holes for arguments to generator function. 2150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); 2151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadSharedFunctionInfoSpecialField(rdx, rdx, 2152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SharedFunctionInfo::kFormalParameterCountOffset); 2153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(rcx, Heap::kTheHoleValueRootIndex); 2154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label push_argument_holes, push_frame; 2155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&push_argument_holes); 2156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(rdx, Immediate(1)); 2157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(carry, &push_frame); 2158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rcx); 2159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&push_argument_holes); 2160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Enter a new JavaScript frame, and initialize its slots as they were when 2162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the generator was suspended. 2163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label resume_frame; 2164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&push_frame); 2165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ call(&resume_frame); 2166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done); 2167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&resume_frame); 2168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pushq(rbp); // Caller's frame pointer. 2169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbp, rsp); 2170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rsi); // Callee's context. 2171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdi); // Callee's JS Function. 2172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the operand stack size. 2174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, FieldOperand(rbx, JSGeneratorObject::kOperandStackOffset)); 2175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, FieldOperand(rdx, FixedArray::kLengthOffset)); 2176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiToInteger32(rdx, rdx); 2177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If we are sending a value and there is no operand stack, we can jump back 2179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // in directly. 2180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (resume_mode == JSGeneratorObject::NEXT) { 2181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow_resume; 2182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rdx, Immediate(0)); 2183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &slow_resume); 2184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); 2185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiToInteger64(rcx, 2186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(rbx, JSGeneratorObject::kContinuationOffset)); 2187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(rdx, rcx); 2188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(FieldOperand(rbx, JSGeneratorObject::kContinuationOffset), 2189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)); 2190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(rdx); 2191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&slow_resume); 2192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Otherwise, we push holes for the operand stack and call the runtime to fix 2195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // up the stack and the handlers. 2196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label push_operand_holes, call_resume; 2197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&push_operand_holes); 2198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(rdx, Immediate(1)); 2199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(carry, &call_resume); 2200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rcx); 2201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&push_operand_holes); 2202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&call_resume); 2203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rbx); 2204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(result_register()); 2205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Smi::FromInt(resume_mode)); 2206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); 2207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Not reached: the runtime call returns elsewhere. 2208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Abort(kGeneratorFailedToResume); 2209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Reach here when generator is closed. 2211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&closed_state); 2212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (resume_mode == JSGeneratorObject::NEXT) { 2213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return completed iterator result when generator is closed. 2214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushRoot(Heap::kUndefinedValueRootIndex); 2215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pop value from top-of-stack slot; box result into result register. 2216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCreateIteratorResult(true); 2217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Throw the provided value. 2219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); 2220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kThrow, 1); 2221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done); 2223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Throw error if we attempt to operate on a running generator. 2225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&wrong_state); 2226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rbx); 2227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); 2228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 2230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(result_register()); 2231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCreateIteratorResult(bool done) { 2235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label gc_required; 2236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label allocated; 2237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> map(isolate()->native_context()->iterator_result_map()); 2239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Allocate(map->instance_size(), rax, rcx, rdx, &gc_required, TAG_OBJECT); 2241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&allocated); 2242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&gc_required); 2244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Smi::FromInt(map->instance_size())); 2245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kAllocateInNewSpace, 1); 2246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(context_register(), 2247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(rbp, StandardFrameConstants::kContextOffset)); 2248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&allocated); 2250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rbx, map); 2251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rcx); 2252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rdx, isolate()->factory()->ToBoolean(done)); 2253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(map->instance_size(), 5 * kPointerSize); 2254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rax, HeapObject::kMapOffset), rbx); 2255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(FieldOperand(rax, JSObject::kPropertiesOffset), 2256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate()->factory()->empty_fixed_array()); 2257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(FieldOperand(rax, JSObject::kElementsOffset), 2258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate()->factory()->empty_fixed_array()); 2259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rax, JSGeneratorObject::kResultValuePropertyOffset), 2260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch rcx); 2261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rax, JSGeneratorObject::kResultDonePropertyOffset), 2262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch rdx); 2263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Only the value field needs a write barrier, as the other values are in the 2265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // root set. 2266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteField(rax, JSGeneratorObject::kResultValuePropertyOffset, 2267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch rcx, rdx, kDontSaveFPRegs); 2268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2271d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 2272e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(prop->position()); 2273e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Literal* key = prop->key()->AsLiteral(); 2274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(LoadDescriptor::NameRegister(), key->value()); 2275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 2276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(VectorLoadICDescriptor::SlotRegister(), 2277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(prop->PropertyFeedbackSlot())); 2278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(NOT_CONTEXTUAL); 2279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); 2281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) { 2286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetSourcePosition(prop->position()); 2287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Literal* key = prop->key()->AsLiteral(); 2288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!key->value()->IsSmi()); 2289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(prop->IsSuperAccess()); 2290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SuperReference* super_ref = prop->obj()->AsSuperReference(); 2292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitLoadHomeObject(super_ref); 2293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); 2294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(super_ref->this_var()); 2295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(key->value()); 2296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kLoadFromSuper, 3); 2297e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 2298e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2299e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2300d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 2301e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(prop->position()); 2302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code(); 2303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 2304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(VectorLoadICDescriptor::SlotRegister(), 2305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(prop->PropertyFeedbackSlot())); 2306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic); 2307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, prop->PropertyFeedbackId()); 2309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2310e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 2311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, 231480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Token::Value op, 231580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen OverwriteMode mode, 231680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Expression* left, 2317e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Expression* right) { 231880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Do combined smi check of the operands. Left operand is on the 231980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // stack (popped into rdx). Right operand is in rax but moved into 232080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // rcx to make the shifts easier. 2321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done, stub_call, smi_case; 2322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rdx); 2323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, rax); 2324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ orp(rax, rdx); 23251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block JumpPatchSite patch_site(masm_); 2326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch patch_site.EmitJumpIfSmi(rax, &smi_case, Label::kNear); 232780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 232880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&stub_call); 2329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, rcx); 2330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op, mode).code(); 2331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(code, expr->BinaryOperationFeedbackId()); 23323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 2333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 233480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 233580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&smi_case); 233680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen switch (op) { 233780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SAR: 233880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiShiftArithmeticRight(rax, rdx, rcx); 233980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 234080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SHL: 2341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiShiftLeft(rax, rdx, rcx, &stub_call); 234280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 234380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SHR: 234480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiShiftLogicalRight(rax, rdx, rcx, &stub_call); 234580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 234680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::ADD: 234780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiAdd(rax, rdx, rcx, &stub_call); 234880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 234980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::SUB: 235080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiSub(rax, rdx, rcx, &stub_call); 235180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 235280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::MUL: 235380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiMul(rax, rdx, rcx, &stub_call); 235480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 235580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::BIT_OR: 235680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiOr(rax, rdx, rcx); 235780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 235880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::BIT_AND: 235980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiAnd(rax, rdx, rcx); 236080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 236180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen case Token::BIT_XOR: 236280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ SmiXor(rax, rdx, rcx); 236380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 236480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen default: 236580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen UNREACHABLE(); 236680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen break; 236780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 236880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 236980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&done); 23700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 237180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 237280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 237380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 2374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, 2375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Token::Value op, 237680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen OverwriteMode mode) { 2377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rdx); 2378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op, mode).code(); 23793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. 2380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(code, expr->BinaryOperationFeedbackId()); 23813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 23820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2383e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 2384e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 2385e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 23863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitAssignment(Expression* expr) { 2387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->IsValidReferenceExpression()); 2388f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2389f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Left-hand side can only be a property, a global or a (parameter or local) 23903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // slot. 2391f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 2392f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke LhsKind assign_type = VARIABLE; 2393f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Property* prop = expr->AsProperty(); 2394f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (prop != NULL) { 2395f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke assign_type = (prop->key()->IsPropertyName()) 2396f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ? NAMED_PROPERTY 2397f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke : KEYED_PROPERTY; 2398f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2399f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2400f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke switch (assign_type) { 2401f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case VARIABLE: { 2402f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Variable* var = expr->AsVariableProxy()->var(); 24030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EffectContext context(this); 24040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitVariableAssignment(var, Token::ASSIGN); 2405f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 2406f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2407f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case NAMED_PROPERTY: { 2408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); // Preserve value. 24090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(prop->obj()); 2410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(StoreDescriptor::ReceiverRegister(), rax); 2411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(StoreDescriptor::ValueRegister()); // Restore value. 2412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(StoreDescriptor::NameRegister(), 2413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch prop->key()->AsLiteral()->value()); 2414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallStoreIC(); 2415f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 2416f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2417f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case KEYED_PROPERTY: { 2418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); // Preserve value. 24193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(prop->obj()); 24203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForAccumulatorValue(prop->key()); 2421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(StoreDescriptor::NameRegister(), rax); 2422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(StoreDescriptor::ReceiverRegister()); 2423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(StoreDescriptor::ValueRegister()); // Restore value. 2424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = 2425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code(); 2426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic); 2427f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 2428f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2429f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 2430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(rax); 2431f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2432f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2433f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( 2435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Variable* var, MemOperand location) { 2436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(location, rax); 2437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->IsContextSlot()) { 2438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, rax); 2439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWriteContextSlot( 2440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs); 2441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2445d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitVariableAssignment(Variable* var, 24460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Token::Value op) { 2447589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsUnallocated()) { 2448589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Global var, const, or let. 2449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(StoreDescriptor::NameRegister(), var->name()); 2450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand()); 2451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallStoreIC(); 2452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (op == Token::INIT_CONST_LEGACY) { 2454589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Const initializers need a write barrier. 2455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!var->IsParameter()); // No const parameters. 2456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (var->IsLookupSlot()) { 2457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); 2458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rsi); 2459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(var->name()); 2460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3); 2461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackLocal() || var->IsContextSlot()); 2463589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Label skip; 2464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand location = VarOperand(var, rcx); 2465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, location); 2466589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); 2467589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ j(not_equal, &skip); 2468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitStoreToStackLocalOrContextSlot(var, location); 2469589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ bind(&skip); 2470e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2471e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 24723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (var->mode() == LET && op != Token::INIT_LET) { 2473589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Non-initializing assignment to let variable needs a write barrier. 2474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!var->IsLookupSlot()); 2475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 2476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label assign; 2477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand location = VarOperand(var, rcx); 2478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, location); 2479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); 2480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &assign, Label::kNear); 2481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(var->name()); 2482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kThrowReferenceError, 1); 2483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&assign); 2484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitStoreToStackLocalOrContextSlot(var, location); 2485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (!var->is_const_mode() || op == Token::INIT_CONST) { 2487589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsLookupSlot()) { 2488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Assignment to var. 2489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); // Value. 2490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rsi); // Context. 2491589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Push(var->name()); 2492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Smi::FromInt(strict_mode())); 2493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kStoreLookupSlot, 4); 2494589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 2495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Assignment to var or initializing assignment to let/const in harmony 2496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // mode. 2497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 2498589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch MemOperand location = VarOperand(var, rcx); 2499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (generate_debug_code_ && op == Token::INIT_LET) { 2500589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Check for an uninitialized let binding. 2501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, location); 2502589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); 2503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(equal, kLetBindingReInitialization); 25043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitStoreToStackLocalOrContextSlot(var, location); 25063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 25073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2508589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Non-initializing assignments to consts are ignored. 25093ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 25103ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 25113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2512d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 2513d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a named store IC. 2514d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Property* prop = expr->target()->AsProperty(); 2515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(prop != NULL); 2516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(prop->key()->IsLiteral()); 2517d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2518e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source code position before IC call. 2519e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(expr->position()); 2520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(StoreDescriptor::NameRegister(), prop->key()->AsLiteral()->value()); 2521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(StoreDescriptor::ReceiverRegister()); 2522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallStoreIC(expr->AssignmentFeedbackId()); 2523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2524086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 2525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(rax); 2526d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2527d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2528d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2529d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 2530d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Assignment to a property, using a keyed store IC. 2531d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(StoreDescriptor::NameRegister()); // Key. 2533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(StoreDescriptor::ReceiverRegister()); 2534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(StoreDescriptor::ValueRegister().is(rax)); 2535e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Record source code position before IC call. 2536e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke SetSourcePosition(expr->position()); 2537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code(); 2538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, expr->AssignmentFeedbackId()); 2539d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2540086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 25410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 2542d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2543d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2544d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2545d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitProperty(Property* expr) { 2546d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Property"); 2547d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Expression* key = expr->key(); 2548d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2549e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (key->IsPropertyName()) { 2550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!expr->IsSuperAccess()) { 2551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(expr->obj()); 2552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!rax.is(LoadDescriptor::ReceiverRegister())); 2553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(LoadDescriptor::ReceiverRegister(), rax); 2554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitNamedPropertyLoad(expr); 2555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitNamedSuperPropertyLoad(expr); 2557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(expr->LoadId(), TOS_REG); 2559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(rax); 2560d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 25610d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->obj()); 25620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->key()); 2563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(LoadDescriptor::NameRegister(), rax); 2564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(LoadDescriptor::ReceiverRegister()); 2565e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitKeyedPropertyLoad(expr); 2566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(rax); 2567d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2568d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2570d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::CallIC(Handle<Code> code, 2572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch TypeFeedbackId ast_id) { 2573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ic_total_count_++; 2574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ call(code, RelocInfo::CODE_TARGET, ast_id); 2575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Code common for calls using the IC. 2579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCallWithLoadIC(Call* expr) { 2580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* callee = expr->expression(); 2581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallICState::CallType call_type = 2583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch callee->IsVariableProxy() ? CallICState::FUNCTION : CallICState::METHOD; 2584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the target function. 2585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (call_type == CallICState::FUNCTION) { 2586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { StackValueContext context(this); 2587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitVariableLoad(callee->AsVariableProxy()); 2588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailout(callee, NO_REGISTERS); 25893e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 2590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push undefined as receiver. This is patched in the method prologue if it 2591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is a sloppy mode method. 2592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(isolate()->factory()->undefined_value()); 2593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the function from the receiver. 2595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(callee->IsProperty()); 2596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!callee->AsProperty()->IsSuperAccess()); 2597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0)); 2598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitNamedPropertyLoad(callee->AsProperty()); 2599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); 2600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the target function under the receiver. 2601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Operand(rsp, 0)); 2602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rsp, kPointerSize), rax); 26033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCall(expr, call_type); 2606d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2607d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2608d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) { 2610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* callee = expr->expression(); 2611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(callee->IsProperty()); 2612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Property* prop = callee->AsProperty(); 2613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(prop->IsSuperAccess()); 2614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetSourcePosition(prop->position()); 2616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Literal* key = prop->key()->AsLiteral(); 2617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!key->value()->IsSmi()); 2618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the function from the receiver. 2619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SuperReference* super_ref = prop->obj()->AsSuperReference(); 2620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitLoadHomeObject(super_ref); 2621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); 2622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(super_ref->this_var()); 2623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); 2624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Operand(rsp, kPointerSize)); 2625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); 2626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(key->value()); 2627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Stack here: 2629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - home_object 2630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - this (receiver) 2631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - home_object <-- LoadFromSuper will pop here and below. 2632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - this (receiver) 2633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - key 2634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kLoadFromSuper, 3); 2635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Replace home_object with target function. 2637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rsp, kPointerSize), rax); 2638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Stack here: 2640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - target function 2641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // - this (receiver) 2642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCall(expr, CallICState::METHOD); 2643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 2644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Common code for calls using the IC. 2647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, 2648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* key) { 26498a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Load the key. 26508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang VisitForAccumulatorValue(key); 26518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 2652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Expression* callee = expr->expression(); 26538a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 2654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the function from the receiver. 2655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(callee->IsProperty()); 2656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0)); 2657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(LoadDescriptor::NameRegister(), rax); 2658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitKeyedPropertyLoad(callee->AsProperty()); 2659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); 2660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the target function under the receiver. 2662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Operand(rsp, 0)); 2663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rsp, kPointerSize), rax); 2664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCall(expr, CallICState::METHOD); 26669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen} 26679dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 26689dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 2669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) { 2670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the arguments. 2671d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 2672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 2673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { PreservePositionScope scope(masm()->positions_recorder()); 26743e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu for (int i = 0; i < arg_count; i++) { 26753e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(args->at(i)); 26763e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 2677d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record source position of the IC call. 2680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetSourcePosition(expr->position()); 2681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = CallIC::initialize_stub( 2682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate(), arg_count, call_type); 2683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rdx, Smi::FromInt(expr->CallFeedbackSlot())); 2684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); 2685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Don't assign a type feedback id to the IC, since type feedback is provided 2686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // by the vector above. 2687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic); 2688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2689086aeeaae12517475c22695a200be45495516549Ben Murdoch RecordJSReturnSite(expr); 2690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 26913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Restore context register. 2692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 26933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Discard the function left on TOS. 26940d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->DropAndPlug(1, rax); 2695d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 26983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { 2699e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Push copy of the first argument or undefined if it doesn't exist. 2700e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (arg_count > 0) { 2701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Operand(rsp, arg_count * kPointerSize)); 2702e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 2703e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ PushRoot(Heap::kUndefinedValueRootIndex); 2704e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2705e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the enclosing function. 2707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 2708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2709e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Push the receiver of the enclosing function and do runtime call. 2710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StackArgumentsAccessor args(rbp, info_->scope()->num_parameters()); 2711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(args.GetReceiverOperand()); 2712e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 27133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Push the language mode. 2714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Smi::FromInt(strict_mode())); 27153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Push the start position of the scope the calls resides in. 27173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(Smi::FromInt(scope()->start_position())); 2718e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 27193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Do the runtime call. 2720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 6); 2721e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2722e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2723e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2724d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCall(Call* expr) { 2725086aeeaae12517475c22695a200be45495516549Ben Murdoch#ifdef DEBUG 2726086aeeaae12517475c22695a200be45495516549Ben Murdoch // We want to verify that RecordJSReturnSite gets called on all paths 2727086aeeaae12517475c22695a200be45495516549Ben Murdoch // through this function. Avoid early returns. 2728086aeeaae12517475c22695a200be45495516549Ben Murdoch expr->return_is_recorded_ = false; 2729086aeeaae12517475c22695a200be45495516549Ben Murdoch#endif 2730086aeeaae12517475c22695a200be45495516549Ben Murdoch 2731d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ Call"); 2732589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Expression* callee = expr->expression(); 2733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Call::CallType call_type = expr->GetCallType(isolate()); 2734d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (call_type == Call::POSSIBLY_EVAL_CALL) { 2736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval 2737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to resolve the function we need to call and the receiver of the call. 2738589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Then we call the resolved function using the given arguments. 2739f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ZoneList<Expression*>* args = expr->arguments(); 2740f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int arg_count = args->length(); 2741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { PreservePositionScope pos_scope(masm()->positions_recorder()); 2742589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VisitForStackValue(callee); 27433e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu __ PushRoot(Heap::kUndefinedValueRootIndex); // Reserved receiver slot. 2744f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27453e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Push the arguments. 27463e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu for (int i = 0; i < arg_count; i++) { 27473e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu VisitForStackValue(args->at(i)); 27483e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 2749f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2750589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Push a copy of the function (found below the arguments) and resolve 2751589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // eval. 2752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Operand(rsp, (arg_count + 1) * kPointerSize)); 27533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EmitResolvePossiblyDirectEval(arg_count); 2754f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 27553e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // The runtime call returns a pair of values in rax (function) and 27563e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // rdx (receiver). Touch up the stack with the right values. 2757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rsp, (arg_count + 0) * kPointerSize), rdx); 2758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rsp, (arg_count + 1) * kPointerSize), rax); 27593e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 2760f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Record source position for debugger. 2761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetSourcePosition(expr->position()); 2762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS); 2763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); 2764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 2765086aeeaae12517475c22695a200be45495516549Ben Murdoch RecordJSReturnSite(expr); 2766f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Restore context register. 2767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 27680d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->DropAndPlug(1, rax); 2769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (call_type == Call::GLOBAL_CALL) { 2770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCallWithLoadIC(expr); 2771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (call_type == Call::LOOKUP_SLOT_CALL) { 277359151504615d929945dc59db37bf1166937748c6Steve Block // Call to a lookup slot (dynamically introduced variable). 2774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VariableProxy* proxy = callee->AsVariableProxy(); 277559151504615d929945dc59db37bf1166937748c6Steve Block Label slow, done; 277659151504615d929945dc59db37bf1166937748c6Steve Block 2777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { PreservePositionScope scope(masm()->positions_recorder()); 2778589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Generate code for loading from variables potentially shadowed by 2779589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // eval-introduced variables. 2780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done); 2781086aeeaae12517475c22695a200be45495516549Ben Murdoch } 2782589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ bind(&slow); 2783589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Call the runtime to find the function to call (returned in rax) and 2784589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // the object holding it (returned in rdx). 2785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(context_register()); 2786589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch __ Push(proxy->name()); 2787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kLoadLookupSlot, 2); 2788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); // Function. 2789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdx); // Receiver. 2790086aeeaae12517475c22695a200be45495516549Ben Murdoch 2791589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // If fast case code has been generated, emit code to push the function 2792589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // and receiver and have the slow path jump around this code. 2793086aeeaae12517475c22695a200be45495516549Ben Murdoch if (done.is_linked()) { 2794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label call; 2795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&call, Label::kNear); 2796086aeeaae12517475c22695a200be45495516549Ben Murdoch __ bind(&done); 2797086aeeaae12517475c22695a200be45495516549Ben Murdoch // Push function. 2798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); 2799589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // The receiver is implicitly the global receiver. Indicate this by 2800589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // passing the hole to the call function stub. 2801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushRoot(Heap::kUndefinedValueRootIndex); 2802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&call); 280359151504615d929945dc59db37bf1166937748c6Steve Block } 280459151504615d929945dc59db37bf1166937748c6Steve Block 2805589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // The receiver is either the global receiver or an object found by 2806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // LoadContextSlot. 2807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCall(expr); 2808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (call_type == Call::PROPERTY_CALL) { 2809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Property* property = callee->AsProperty(); 2810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch bool is_named_call = property->key()->IsPropertyName(); 2811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // super.x() is handled in EmitCallWithLoadIC. 2812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (property->IsSuperAccess() && is_named_call) { 2813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitSuperCallWithLoadIC(expr); 2814d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 2815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 2816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PreservePositionScope scope(masm()->positions_recorder()); 2817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(property->obj()); 2818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (is_named_call) { 2820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCallWithLoadIC(expr); 2821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 2822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitKeyedCallWithLoadIC(expr, property->key()); 2823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 2824d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 28253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } else { 2826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(call_type == Call::OTHER_CALL); 2827589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Call to an arbitrary expression not handled specially above. 2828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { PreservePositionScope scope(masm()->positions_recorder()); 2829589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VisitForStackValue(callee); 28303e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu } 2831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PushRoot(Heap::kUndefinedValueRootIndex); 2832d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Emit function call. 2833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitCall(expr); 2834d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 2835086aeeaae12517475c22695a200be45495516549Ben Murdoch 2836086aeeaae12517475c22695a200be45495516549Ben Murdoch#ifdef DEBUG 2837086aeeaae12517475c22695a200be45495516549Ben Murdoch // RecordJSReturnSite should have been called. 2838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->return_is_recorded_); 2839086aeeaae12517475c22695a200be45495516549Ben Murdoch#endif 2840d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 2841d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2842d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2843d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallNew(CallNew* expr) { 2844d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CallNew"); 2845d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // According to ECMA-262, section 11.2.2, page 44, the function 2846d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // expression in new calls must be evaluated before the 2847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // arguments. 2848d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 284980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Push constructor on the stack. If it's not a function it's used as 285080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // receiver for CALL_NON_FUNCTION, otherwise the value on the stack is 285180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ignored. 28520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->expression()); 2853d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2854d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Push the arguments ("left-to-right") on the stack. 2855d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ZoneList<Expression*>* args = expr->arguments(); 2856d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int arg_count = args->length(); 2857d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block for (int i = 0; i < arg_count; i++) { 28580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(i)); 28593ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2860d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2861d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Call the construct call builtin that handles allocation and 2862d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // constructor invocation. 2863d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SetSourcePosition(expr->position()); 2864d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 286580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Load function and argument count into rdi and rax. 2866d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ Set(rax, arg_count); 2867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, Operand(rsp, arg_count * kPointerSize)); 2868d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 28693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Record call targets in unoptimized code, but not in the snapshot. 2870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_pretenuring_call_new) { 2871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot()); 2872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->AllocationSiteFeedbackSlot() == 2873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch expr->CallNewFeedbackSlot() + 1); 28743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 28753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rbx, FeedbackVector()); 2877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rdx, Smi::FromInt(expr->CallNewFeedbackSlot())); 2878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 2879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallConstructStub stub(isolate(), RECORD_CONSTRUCTOR_TARGET); 28803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Call(stub.GetCode(), RelocInfo::CONSTRUCT_CALL); 28813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutForId(expr->ReturnId(), TOS_REG); 28820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 28833ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 28843ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 28853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 28863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { 28873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 2889f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 28900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2891f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2892f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2893f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2894f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 289580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 28960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 28970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2898f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 28993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2900f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, if_true); 2901f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(if_false); 2902f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2904f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2905f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2906f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) { 29083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 2910f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2912f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2913f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2914f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2915f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 291680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 29170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 29180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2919f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 2921f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Condition non_negative_smi = masm()->CheckNonNegativeSmi(rax); 2922f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Split(non_negative_smi, if_true, if_false, fall_through); 2923f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29240d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2925f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2926f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsObject(CallRuntime* expr) { 29293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 2931f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2933f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2934f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2935f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2936f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 293780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 29380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 29390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2940f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2941f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, if_false); 2942f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CompareRoot(rax, Heap::kNullValueRootIndex); 2943f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 2944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 2945f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Undetectable objects behave like undefined when tested with typeof. 2946f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 2947f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Immediate(1 << Map::kIsUndetectable)); 2948f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_zero, if_false); 2949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movzxbp(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 2950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rbx, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE)); 2951f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(below, if_false); 2952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rbx, Immediate(LAST_NONCALLABLE_SPEC_OBJECT_TYPE)); 29533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 295480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(below_equal, if_true, if_false, fall_through); 2955f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 2957f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 2958f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2959f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) { 29613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 29633bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 29640d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 29653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 29663bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label materialize_true, materialize_false; 29673bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* if_true = NULL; 29683bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Label* if_false = NULL; 296980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 29700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 29710d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 29723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 29733bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ JumpIfSmi(rax, if_false); 29743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rbx); 29753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 297680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(above_equal, if_true, if_false, fall_through); 29773bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 29780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 29793bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch} 29803bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 29813bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 29823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) { 29833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 2984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 2985f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 29860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 2987f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2988f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 2989f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 2990f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 299180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 29920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 29930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 2994f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 2995f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, if_false); 2996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 2997f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 2998f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Immediate(1 << Map::kIsUndetectable)); 29993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 300080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(not_zero, if_true, if_false, fall_through); 3001f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 30020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 3003f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3004f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3005f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3006756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickvoid FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( 30073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallRuntime* expr) { 30083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 3010756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 30110d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 3012756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 3013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false, skip_lookup; 3014756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label* if_true = NULL; 3015756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick Label* if_false = NULL; 301680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 30170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 30180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 3019756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 3020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AssertNotSmi(rax); 30218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 30228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Check whether this map has already been checked to be safe for default 30238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // valueOf. 3024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 30258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ testb(FieldOperand(rbx, Map::kBitField2Offset), 30268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf)); 3027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &skip_lookup); 30288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 30298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Check for fast case object. Generate false result for slow case object. 3030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, FieldOperand(rax, JSObject::kPropertiesOffset)); 3031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, FieldOperand(rcx, HeapObject::kMapOffset)); 30328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ CompareRoot(rcx, Heap::kHashTableMapRootIndex); 30338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ j(equal, if_false); 30348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 3035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Look for valueOf string in the descriptor array, and indicate false if 3036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // found. Since we omit an enumeration index check, if it is added via a 3037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // transition that shares its descriptor array, this is a false positive. 3038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label entry, loop, done; 3039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Skip loop if no descriptors are valid. 3041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ NumberOfOwnDescriptors(rcx, rbx); 3042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rcx, Immediate(0)); 3043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &done); 3044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadInstanceDescriptors(rbx, r8); 3046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rbx: descriptor array. 3047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // rcx: valid entries in the descriptor array. 30488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Calculate the end of the descriptor array. 3049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ imulp(rcx, rcx, Immediate(DescriptorArray::kDescriptorSize)); 3050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(rcx, 3051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(r8, rcx, times_pointer_size, DescriptorArray::kFirstOffset)); 30528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Calculate location of the first key name. 3053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(r8, Immediate(DescriptorArray::kFirstOffset)); 30548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Loop through all the keys in the descriptor array. If one of these is the 3055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // internalized string "valueOf" the result is false. 30568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ jmp(&entry); 30578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ bind(&loop); 3058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, FieldOperand(r8, 0)); 3059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Cmp(rdx, isolate()->factory()->value_of_string()); 30608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ j(equal, if_false); 3061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(r8, Immediate(DescriptorArray::kDescriptorSize * kPointerSize)); 30628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ bind(&entry); 3063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(r8, rcx); 30648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ j(not_equal, &loop); 30658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 3066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 3067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Set the bit in the map to indicate that there is no local valueOf field. 3069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ orp(FieldOperand(rbx, Map::kBitField2Offset), 3070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(1 << Map::kStringWrapperSafeForDefaultValueOf)); 3071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&skip_lookup); 30738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 3074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If a valueOf property is not found on the object check that its 30758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // prototype is the un-modified String prototype. If not result is false. 3076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, FieldOperand(rbx, Map::kPrototypeOffset)); 3077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testp(rcx, Immediate(kSmiTagMask)); 30788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ j(zero, if_false); 3079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, FieldOperand(rcx, HeapObject::kMapOffset)); 3080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 3081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, FieldOperand(rdx, GlobalObject::kNativeContextOffset)); 3082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rcx, 30838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ContextOperand(rdx, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); 30843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(equal, if_true, if_false, fall_through); 3086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 30870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 3088756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 3089756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 3090756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 30913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsFunction(CallRuntime* expr) { 30923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 3094f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 30950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 3096f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3097f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 3098f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 3099f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 310080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 31010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 31020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 3103f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3104f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, if_false); 3105f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); 31063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 310780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 3108f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 31090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 3110f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3111f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3112f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) { 3114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 3116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); 3118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label materialize_true, materialize_false; 3120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_true = NULL; 3121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* if_false = NULL; 3122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* fall_through = NULL; 3123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 3124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &if_true, &if_false, &fall_through); 3125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> map = masm()->isolate()->factory()->heap_number_map(); 3127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CheckMap(rax, map, if_false, DO_SMI_CHECK); 3128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpl(FieldOperand(rax, HeapNumber::kExponentOffset), 3129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(0x1)); 3130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(no_overflow, if_false); 3131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpl(FieldOperand(rax, HeapNumber::kMantissaOffset), 3132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(0x00000000)); 3133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(equal, if_true, if_false, fall_through); 3135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(if_true, if_false); 3137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 31403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsArray(CallRuntime* expr) { 31413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 3143f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 31440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 3145f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3146f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 3147f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 3148f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 314980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 31500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 31510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 3152f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3153f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, if_false); 3154f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx); 31553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 315680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 3157f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 31580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 3159f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3160f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3161f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 31623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) { 31633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 3165f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 31660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 3167f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3168f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 3169f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 3170f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 317180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 31720d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 31730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 3174f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3175f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, if_false); 3176f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx); 31773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 317880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 3179f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 31800d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 3181f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3182f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3183f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3184f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 31853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) { 3186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->arguments()->length() == 0); 3187f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3188f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 3189f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 3190f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 319180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 31920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 31930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 3194f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3195f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the frame pointer for the calling frame. 3196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 3197f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3198f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Skip the arguments adaptor frame if it exists. 3199f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label check_frame_marker; 320044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Cmp(Operand(rax, StandardFrameConstants::kContextOffset), 320144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 3202f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &check_frame_marker); 3203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset)); 3204f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3205f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check the marker in the calling frame. 3206f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&check_frame_marker); 320744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Cmp(Operand(rax, StandardFrameConstants::kMarkerOffset), 320844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Smi::FromInt(StackFrame::CONSTRUCT)); 32093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 321080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 3211f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 3213f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3214f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3215f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) { 32173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 2); 3219f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3220f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the two objects into registers and perform the comparison. 32210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 32220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 3223f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3224f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 3225f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 3226f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 322780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 32280d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 32290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 3230f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rbx); 3232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rax, rbx); 32333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 323480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 3235f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 3237f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3238f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3239f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitArguments(CallRuntime* expr) { 32413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 3243f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 324480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ArgumentsAccessStub expects the key in rdx and the formal 324580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // parameter count in rax. 32460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 3247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, rax); 32483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Move(rax, Smi::FromInt(info_->scope()->num_parameters())); 3249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ArgumentsAccessStub stub(isolate(), ArgumentsAccessStub::READ_ELEMENT); 3250f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 32510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3252f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3253f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3254f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) { 3256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->arguments()->length() == 0); 3257f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label exit; 3259f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Get the number of formal parameters. 32603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Move(rax, Smi::FromInt(info_->scope()->num_parameters())); 3261f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3262f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check if the calling frame is an arguments adaptor frame. 3263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 326444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset), 326544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 3266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, &exit, Label::kNear); 3267f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3268f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Arguments adaptor case: Read the arguments length from the 3269f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // adaptor frame. 3270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 3271f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3272f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&exit); 3273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AssertSmi(rax); 32740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3275f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3276f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3277f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitClassOf(CallRuntime* expr) { 32793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 3281f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done, null, function, non_function_constructor; 3282f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32830d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 3284f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3285f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi, we return null. 3286f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, &null); 3287f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3288f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check that the object is a JS object but take special care of JS 3289f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // functions to make sure they have 'Function' as their class. 32903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Assume that there are only two callable types, and one of them is at 32913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // either end of the type range for JS object types. Saves extra comparisons. 32923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); 32933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rax); 32943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Map is now in rax. 3295f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(below, &null); 32963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == 32973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FIRST_SPEC_OBJECT_TYPE + 1); 32983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, &function); 32993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpInstanceType(rax, LAST_SPEC_OBJECT_TYPE); 33013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == 33023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LAST_SPEC_OBJECT_TYPE - 1); 33033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, &function); 33043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Assume that there is no larger type. 33053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == LAST_TYPE - 1); 33063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if the constructor in the map is a JS function. 3308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, FieldOperand(rax, Map::kConstructorOffset)); 3309f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); 3310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &non_function_constructor); 3311f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3312f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // rax now contains the constructor function. Grab the 3313f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // instance class name from there. 3314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset)); 3315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, FieldOperand(rax, SharedFunctionInfo::kInstanceClassNameOffset)); 3316f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 3317f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3318f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Functions have class 'Function'. 3319f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&function); 3320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rax, isolate()->factory()->Function_string()); 3321f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 3322f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Objects with a non-function constructor have class 'Object'. 3324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&non_function_constructor); 3325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rax, isolate()->factory()->Object_string()); 3326f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 3327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3328f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Non-JS objects have class null. 3329f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&null); 3330f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(rax, Heap::kNullValueRootIndex); 3331f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3332f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // All done. 3333f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 3334f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 33350d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3336f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3337f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3338f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 33393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitSubString(CallRuntime* expr) { 3340f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the stub. 3341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SubStringStub stub(isolate()); 33423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 3); 33440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 33450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 33460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 3347f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 33480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3349f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3350f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3351f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 33523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitRegExpExec(CallRuntime* expr) { 3353f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the stub. 3354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RegExpExecStub stub(isolate()); 33553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 4); 33570d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 33580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 33590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(2)); 33600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(3)); 3361f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 33620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3363f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3364f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3365f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 33663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitValueOf(CallRuntime* expr) { 33673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 3369f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 33700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); // Load the object. 3371f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3372f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 3373f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi return the object. 3374f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rax, &done); 3375f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is not a value type, return the object. 3376f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rax, JS_VALUE_TYPE, rbx); 3377f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &done); 3378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, FieldOperand(rax, JSValue::kValueOffset)); 3379f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3380f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 33810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3382f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3383f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3384f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 33853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitDateField(CallRuntime* expr) { 33863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 2); 3388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_NE(NULL, args->at(1)->AsLiteral()); 3389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value())); 33903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForAccumulatorValue(args->at(0)); // Load the object. 33923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label runtime, done, not_date_object; 33943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register object = rax; 33953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register result = rax; 33963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch = rcx; 33973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(object, ¬_date_object); 33993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpObjectType(object, JS_DATE_TYPE, scratch); 3400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, ¬_date_object); 34013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 34023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (index->value() == 0) { 3403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(result, FieldOperand(object, JSDate::kValueOffset)); 3404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done); 34053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 34063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (index->value() < JSDate::kFirstUncachedField) { 34073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); 3408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand stamp_operand = __ ExternalOperand(stamp); 3409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(scratch, stamp_operand); 3410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(scratch, FieldOperand(object, JSDate::kCacheStampOffset)); 34113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &runtime, Label::kNear); 3412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(result, FieldOperand(object, JSDate::kValueOffset + 34133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kPointerSize * index->value())); 34143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done); 34153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 34163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&runtime); 34173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PrepareCallCFunction(2); 3418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(arg_reg_1, object); 3419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(arg_reg_2, index, Assembler::RelocInfoNone()); 34203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); 3421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 3422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done); 34233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(¬_date_object); 3426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kThrowNotDateError, 0); 3427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 3428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(rax); 3429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { 3433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(3, args->length()); 3435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register string = rax; 3437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register index = rbx; 3438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value = rcx; 3439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(0)); // index 3441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(1)); // value 3442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(2)); // string 3443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(value); 3444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(index); 3445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code) { 3447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(__ CheckSmi(value), kNonSmiValue); 3448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(__ CheckSmi(index), kNonSmiValue); 3449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiToInteger32(value, value); 3452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiToInteger32(index, index); 3453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code) { 3455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; 3456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type); 3457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movb(FieldOperand(string, index, times_1, SeqOneByteString::kHeaderSize), 3460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch value); 3461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(string); 3462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 3463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { 3466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(3, args->length()); 3468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register string = rax; 3470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register index = rbx; 3471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value = rcx; 3472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(0)); // index 3474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(1)); // value 3475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(2)); // string 3476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(value); 3477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(index); 3478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code) { 3480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(__ CheckSmi(value), kNonSmiValue); 3481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Check(__ CheckSmi(index), kNonSmiValue); 3482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiToInteger32(value, value); 3485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiToInteger32(index, index); 3486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code) { 3488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; 3489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type); 3490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 3491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 3492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movw(FieldOperand(string, index, times_2, SeqTwoByteString::kHeaderSize), 3493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch value); 34943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(rax); 34953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 34963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 34973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 34983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitMathPow(CallRuntime* expr) { 3499f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Load the arguments on the stack and call the runtime function. 35003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 2); 35020d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 35030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 3504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MathPowStub stub(isolate(), MathPowStub::ON_STACK); 3505e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CallStub(&stub); 35060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3507f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3508f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3509f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 35103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) { 35113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 2); 3513f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 35140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); // Load the object. 35150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); // Load the value. 3516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rbx); // rax = value. rbx = object. 3517f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3518f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label done; 3519f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is a smi, return the value. 3520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ JumpIfSmi(rbx, &done); 3521f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3522f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // If the object is not a value type, return the value. 3523f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CmpObjectType(rbx, JS_VALUE_TYPE, rcx); 3524f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(not_equal, &done); 3525f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3526f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Store the value. 3527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(FieldOperand(rbx, JSValue::kValueOffset), rax); 3528f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Update the write barrier. Save the value as it will be 3529f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // overwritten by the write barrier code and is needed afterward. 3530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, rax); 35313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(rbx, JSValue::kValueOffset, rdx, rcx, kDontSaveFPRegs); 3532f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3533f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 35340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3535f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3536f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3537f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 35383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitNumberToString(CallRuntime* expr) { 35393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(args->length(), 1); 3541f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the argument into rax and call the stub. 3543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(0)); 3544f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NumberToStringStub stub(isolate()); 3546f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 35470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3548f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3549f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3550f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 35513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { 35523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 3554f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 35550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 3556f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 35577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 35587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharFromCodeGenerator generator(rax, rbx); 35597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 35607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 3561f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 35627f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 35637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 3564f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 35657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&done); 35660d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rbx); 35677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 35687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 35697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 35703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { 35713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 2); 35737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 35740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 35750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 35767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 35777f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register object = rbx; 35787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = rax; 35797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = rdx; 35807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 3581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(object); 35827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 35837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label need_conversion; 35847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 35857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 35867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharCodeAtGenerator generator(object, 35877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 35887f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 35897f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 35907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 35917f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &index_out_of_range, 35927f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_NUMBER); 35937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 3594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ jmp(&done); 3595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 35967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_out_of_range); 35977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // When the index is out of range, the spec requires us to return 35987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // NaN. 35997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kNanValueRootIndex); 36007f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 36017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 36027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&need_conversion); 36037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Move the undefined value into the result register, which will 36047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // trigger conversion. 36057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ LoadRoot(result, Heap::kUndefinedValueRootIndex); 36067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 36077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 36087f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 36097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 3610f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3611f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 36120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(result); 3613f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3614f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3615f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 36163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) { 36173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 2); 36197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 36200d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 36210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 36227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 36237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register object = rbx; 36247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register index = rax; 36253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch = rdx; 36267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Register result = rax; 36277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 3628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(object); 36297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 36307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label need_conversion; 36317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label index_out_of_range; 36327f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch Label done; 36337f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch StringCharAtGenerator generator(object, 36347f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch index, 36353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 36367f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch result, 36377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 36387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &need_conversion, 36397f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch &index_out_of_range, 36407f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch STRING_INDEX_IS_NUMBER); 36417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateFast(masm_); 36427f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 36437f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 36447f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&index_out_of_range); 36457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // When the index is out of range, the spec requires us to return 36467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // the empty string. 3647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(result, Heap::kempty_stringRootIndex); 36487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 36497f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 36507f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&need_conversion); 36517f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // Move smi zero into the result register, which will trigger 36527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // conversion. 36537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ Move(result, Smi::FromInt(0)); 36547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ jmp(&done); 36557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 36567f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch NopRuntimeCallHelper call_helper; 36577f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch generator.GenerateSlow(masm_, call_helper); 36587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 36597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __ bind(&done); 36600d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(result); 3661f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3662f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 36637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 36643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { 36653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(2, args->length()); 36670d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 3668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(1)); 3669f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rdx); 3671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED); 3672f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 36730d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3674f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3675f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3676f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 36773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { 36783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(2, args->length()); 3680f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 36810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 36820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 3683f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StringCompareStub stub(isolate()); 3685f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallStub(&stub); 36860d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3687f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3688f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3689f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 36903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitCallFunction(CallRuntime* expr) { 36913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() >= 2); 3693f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int arg_count = args->length() - 2; // 2 ~ receiver and function. 3695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = 0; i < arg_count + 1; i++) { 3696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VisitForStackValue(args->at(i)); 3697f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VisitForAccumulatorValue(args->last()); // Function. 3699f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label runtime, done; 3701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for non-function argument (including proxy). 3702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(rax, &runtime); 3703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); 3704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &runtime); 37053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // InvokeFunction requires the function in rdi. Move it in there. 3707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, result_register()); 3708f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ParameterCount count(arg_count); 3709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ InvokeFunction(rdi, count, CALL_FUNCTION, NullCallWrapper()); 3710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 37113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done); 37123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&runtime); 3714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); 37153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallRuntime(Runtime::kCall, args->length()); 37163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 37173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3719f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3720f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3721f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 37223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { 3723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RegExpConstructResultStub stub(isolate()); 37243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 3); 37260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(0)); 37270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(args->at(1)); 3728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForAccumulatorValue(args->at(2)); 3729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rbx); 3730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rcx); 3731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ CallStub(&stub); 37320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3733f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3734f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3735f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 37363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { 37373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(2, args->length()); 3739f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_NE(NULL, args->at(0)->AsLiteral()); 3741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value(); 3742f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3743f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Handle<FixedArray> jsfunction_result_caches( 3744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate()->native_context()->jsfunction_result_caches()); 3745f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (jsfunction_result_caches->length() <= cache_id) { 3746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Abort(kAttemptToUseUndefinedCache); 3747f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 37480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3749f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 3750f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 3751f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 37520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(1)); 3753f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3754f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register key = rax; 3755f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register cache = rbx; 3756f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Register tmp = rcx; 3757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(cache, ContextOperand(rsi, Context::GLOBAL_OBJECT_INDEX)); 3758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(cache, 3759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(cache, GlobalObject::kNativeContextOffset)); 3760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(cache, 376159151504615d929945dc59db37bf1166937748c6Steve Block ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX)); 3762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(cache, 3763f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id))); 3764f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done, not_found; 376669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 3767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset)); 3768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // tmp now holds finger offset as a smi. 3769f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke SmiIndex index = 3770f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ SmiToIndex(kScratchRegister, tmp, kPointerSizeLog2); 3771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(key, FieldOperand(cache, 3772f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke index.reg, 3773f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke index.scale, 3774f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FixedArray::kHeaderSize)); 3775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(not_equal, ¬_found, Label::kNear); 3776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, FieldOperand(cache, 3777f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke index.reg, 3778f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke index.scale, 3779f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke FixedArray::kHeaderSize + kPointerSize)); 3780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&done, Label::kNear); 3781f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3782f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(¬_found); 3783f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Call runtime to perform the lookup. 3784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(cache); 3785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(key); 3786f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ CallRuntime(Runtime::kGetFromCache, 2); 3787f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3788f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ bind(&done); 37890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 3790f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 3791f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3792f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 37933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { 37943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 379680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 37970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 379880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 379980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label materialize_true, materialize_false; 380080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true = NULL; 380180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false = NULL; 380280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 38030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 38040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 380580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 380680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ testl(FieldOperand(rax, String::kHashFieldOffset), 380780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Immediate(String::kContainsCachedArrayIndexMask)); 38083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 380980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ j(zero, if_true); 381080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ jmp(if_false); 381180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 38120d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 381380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 381480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 381580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 38163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) { 38173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 1); 38190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(args->at(0)); 382080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 3821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AssertString(rax); 3822e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 382380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ movl(rax, FieldOperand(rax, String::kHashFieldOffset)); 3824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(String::kHashShift >= kSmiTagSize); 382580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ IndexFromHash(rax, rax); 382680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 38270d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 382880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 382980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 383080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 3831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitFastOneByteArrayJoin(CallRuntime* expr) { 383244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label bailout, return_result, done, one_char_separator, long_separator, 383344f0eee88ff00398ff7f715fab053374d808c90dSteve Block non_trivial_array, not_size_one_array, loop, 383444f0eee88ff00398ff7f715fab053374d808c90dSteve Block loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry; 38353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* args = expr->arguments(); 3836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(args->length() == 2); 383744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // We will leave the separator on the stack until the end of the function. 383844f0eee88ff00398ff7f715fab053374d808c90dSteve Block VisitForStackValue(args->at(1)); 383944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Load this to rax (= array) 384044f0eee88ff00398ff7f715fab053374d808c90dSteve Block VisitForAccumulatorValue(args->at(0)); 384144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // All aliases of the same register have disjoint lifetimes. 384244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register array = rax; 384344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register elements = no_reg; // Will be rax. 384444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 384544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register index = rdx; 384644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 384744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register string_length = rcx; 384844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 384944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register string = rsi; 385044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 385144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch = rbx; 385244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 385344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register array_length = rdi; 385444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register result_pos = no_reg; // Will be rdi. 385544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 385644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Operand separator_operand = Operand(rsp, 2 * kPointerSize); 385744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Operand result_operand = Operand(rsp, 1 * kPointerSize); 385844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Operand array_length_operand = Operand(rsp, 0 * kPointerSize); 385944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Separator operand is already pushed. Make room for the two 386044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // other stack fields, and clear the direction flag in anticipation 386144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // of calling CopyBytes. 3862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(rsp, Immediate(2 * kPointerSize)); 386344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cld(); 386444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the array is a JSArray 386544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ JumpIfSmi(array, &bailout); 386644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CmpObjectType(array, JS_ARRAY_TYPE, scratch); 386744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(not_equal, &bailout); 386844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 386944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the array has fast elements. 38703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CheckFastElements(scratch, &bailout); 387144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 387244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Array has fast elements, so its length must be a smi. 387344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // If the array has length zero, return the empty string. 3874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(array_length, FieldOperand(array, JSArray::kLengthOffset)); 387544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ SmiCompare(array_length, Smi::FromInt(0)); 387644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(not_zero, &non_trivial_array); 3877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(rax, Heap::kempty_stringRootIndex); 387844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ jmp(&return_result); 387944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 388044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Save the array length on the stack. 388144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&non_trivial_array); 388244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ SmiToInteger32(array_length, array_length); 388344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movl(array_length_operand, array_length); 388444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 388544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Save the FixedArray containing array's elements. 388644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // End of array's live range. 388744f0eee88ff00398ff7f715fab053374d808c90dSteve Block elements = array; 3888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(elements, FieldOperand(array, JSArray::kElementsOffset)); 388944f0eee88ff00398ff7f715fab053374d808c90dSteve Block array = no_reg; 389044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 389144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that all array elements are sequential one-byte strings, and 389344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // accumulate the sum of their lengths, as a smi-encoded value. 389444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Set(index, 0); 389544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Set(string_length, 0); 389644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Loop condition: while (index < array_length). 389744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Live loop registers: index(int32), array_length(int32), string(String*), 389844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // scratch, string_length(int32), elements(FixedArray*). 3899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (generate_debug_code_) { 3900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(index, array_length); 3901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(below, kNoEmptyArraysHereInEmitFastOneByteArrayJoin); 390244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 390344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&loop); 3904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(string, FieldOperand(elements, 390544f0eee88ff00398ff7f715fab053374d808c90dSteve Block index, 390644f0eee88ff00398ff7f715fab053374d808c90dSteve Block times_pointer_size, 390744f0eee88ff00398ff7f715fab053374d808c90dSteve Block FixedArray::kHeaderSize)); 390844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ JumpIfSmi(string, &bailout); 3909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(scratch, FieldOperand(string, HeapObject::kMapOffset)); 391044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movzxbl(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 391144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ andb(scratch, Immediate( 391244f0eee88ff00398ff7f715fab053374d808c90dSteve Block kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); 3913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpb(scratch, Immediate(kStringTag | kOneByteStringTag | kSeqStringTag)); 391444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(not_equal, &bailout); 391544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ AddSmiField(string_length, 3916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(string, SeqOneByteString::kLengthOffset)); 391744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(overflow, &bailout); 391844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ incl(index); 391944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmpl(index, array_length); 392044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(less, &loop); 392144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 392244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Live registers: 392344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // string_length: Sum of string lengths. 392444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // elements: FixedArray of strings. 392544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // index: Array length. 392644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // array_length: Array length. 392744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 392844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // If array_length is 1, return elements[0], a string. 392944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmpl(array_length, Immediate(1)); 393044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(not_equal, ¬_size_one_array); 3931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, FieldOperand(elements, FixedArray::kHeaderSize)); 393244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ jmp(&return_result); 393344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 393444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(¬_size_one_array); 393544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 393644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // End of array_length live range. 393744f0eee88ff00398ff7f715fab053374d808c90dSteve Block result_pos = array_length; 393844f0eee88ff00398ff7f715fab053374d808c90dSteve Block array_length = no_reg; 393944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 394044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Live registers: 394144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // string_length: Sum of string lengths. 394244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // elements: FixedArray of strings. 394344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // index: Array length. 394444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the separator is a sequential one-byte string. 3946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(string, separator_operand); 394744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ JumpIfSmi(string, &bailout); 3948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(scratch, FieldOperand(string, HeapObject::kMapOffset)); 394944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movzxbl(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 395044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ andb(scratch, Immediate( 395144f0eee88ff00398ff7f715fab053374d808c90dSteve Block kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); 3952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpb(scratch, Immediate(kStringTag | kOneByteStringTag | kSeqStringTag)); 395344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(not_equal, &bailout); 395444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 395544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Live registers: 395644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // string_length: Sum of string lengths. 395744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // elements: FixedArray of strings. 395844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // index: Array length. 395944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // string: Separator string. 396044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 396144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Add (separator length times (array_length - 1)) to string_length. 396244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ SmiToInteger32(scratch, 3963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(string, SeqOneByteString::kLengthOffset)); 396444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ decl(index); 396544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ imull(scratch, index); 396644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(overflow, &bailout); 396744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ addl(string_length, scratch); 396844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(overflow, &bailout); 396944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 397044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Live registers and stack values: 397144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // string_length: Total length of result string. 397244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // elements: FixedArray of strings. 3973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AllocateOneByteString(result_pos, string_length, scratch, index, string, 3974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &bailout); 3975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(result_operand, result_pos); 3976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(result_pos, FieldOperand(result_pos, SeqOneByteString::kHeaderSize)); 397744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(string, separator_operand); 3979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiCompare(FieldOperand(string, SeqOneByteString::kLengthOffset), 398044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Smi::FromInt(1)); 398144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(equal, &one_char_separator); 398244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(greater, &long_separator); 398344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 398444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 398544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Empty separator case: 398644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Set(index, 0); 398744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movl(scratch, array_length_operand); 398844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ jmp(&loop_1_condition); 398944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Loop condition: while (index < array_length). 399044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&loop_1); 399144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Each iteration of the loop concatenates one string to the result. 399244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Live values in registers: 399344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // index: which element of the elements array we are adding to the result. 399444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // result_pos: the position to which we are currently copying characters. 399544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // elements: the FixedArray of strings we are joining. 399644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // scratch: array length. 399744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 399844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Get string = array[index]. 3999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(string, FieldOperand(elements, index, 400044f0eee88ff00398ff7f715fab053374d808c90dSteve Block times_pointer_size, 400144f0eee88ff00398ff7f715fab053374d808c90dSteve Block FixedArray::kHeaderSize)); 400244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ SmiToInteger32(string_length, 400344f0eee88ff00398ff7f715fab053374d808c90dSteve Block FieldOperand(string, String::kLengthOffset)); 4004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(string, 4005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(string, SeqOneByteString::kHeaderSize)); 400644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CopyBytes(result_pos, string, string_length); 400744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ incl(index); 400844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&loop_1_condition); 400944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmpl(index, scratch); 401044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(less, &loop_1); // Loop while (index < array_length). 401144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ jmp(&done); 401244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 401344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Generic bailout code used from several places. 401444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&bailout); 401544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 401644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ jmp(&return_result); 401744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 401844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 401944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // One-character separator case 402044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&one_char_separator); 4021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the separator one-byte character value. 402244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Register "string" holds the separator. 4023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movzxbl(scratch, FieldOperand(string, SeqOneByteString::kHeaderSize)); 402444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Set(index, 0); 402544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Jump into the loop after the code that copies the separator, so the first 402644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // element is not preceded by a separator 402744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ jmp(&loop_2_entry); 402844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Loop condition: while (index < length). 402944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&loop_2); 403044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Each iteration of the loop concatenates one string to the result. 403144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Live values in registers: 403244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // elements: The FixedArray of strings we are joining. 403344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // index: which element of the elements array we are adding to the result. 403444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // result_pos: the position to which we are currently copying characters. 403544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // scratch: Separator character. 403644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 403744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Copy the separator character to the result. 403844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movb(Operand(result_pos, 0), scratch); 4039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ incp(result_pos); 404044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 404144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&loop_2_entry); 404244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Get string = array[index]. 4043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(string, FieldOperand(elements, index, 404444f0eee88ff00398ff7f715fab053374d808c90dSteve Block times_pointer_size, 404544f0eee88ff00398ff7f715fab053374d808c90dSteve Block FixedArray::kHeaderSize)); 404644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ SmiToInteger32(string_length, 404744f0eee88ff00398ff7f715fab053374d808c90dSteve Block FieldOperand(string, String::kLengthOffset)); 4048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(string, 4049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(string, SeqOneByteString::kHeaderSize)); 405044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CopyBytes(result_pos, string, string_length); 405144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ incl(index); 405244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmpl(index, array_length_operand); 405344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(less, &loop_2); // End while (index < length). 405444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ jmp(&done); 405544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 405644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 405744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Long separator case (separator is more than one character). 405844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&long_separator); 405944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 406044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Make elements point to end of elements array, and index 406144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // count from -array_length to zero, so we don't need to maintain 406244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // a loop limit. 406344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movl(index, array_length_operand); 4064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(elements, FieldOperand(elements, index, times_pointer_size, 406544f0eee88ff00398ff7f715fab053374d808c90dSteve Block FixedArray::kHeaderSize)); 4066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ negq(index); 406744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 406844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Replace separator string with pointer to its first character, and 406944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // make scratch be its length. 4070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(string, separator_operand); 407144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ SmiToInteger32(scratch, 407244f0eee88ff00398ff7f715fab053374d808c90dSteve Block FieldOperand(string, String::kLengthOffset)); 4073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(string, 4074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(string, SeqOneByteString::kHeaderSize)); 4075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(separator_operand, string); 407644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 407744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Jump into the loop after the code that copies the separator, so the first 407844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // element is not preceded by a separator 407944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ jmp(&loop_3_entry); 408044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Loop condition: while (index < length). 408144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&loop_3); 408244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Each iteration of the loop concatenates one string to the result. 408344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Live values in registers: 408444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // index: which element of the elements array we are adding to the result. 408544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // result_pos: the position to which we are currently copying characters. 408644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // scratch: Separator length. 408744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // separator_operand (rsp[0x10]): Address of first char of separator. 408844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 408944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Copy the separator to the result. 4090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(string, separator_operand); 409144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movl(string_length, scratch); 409244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CopyBytes(result_pos, string, string_length, 2); 409344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 409444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&loop_3_entry); 409544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Get string = array[index]. 4096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(string, Operand(elements, index, times_pointer_size, 0)); 409744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ SmiToInteger32(string_length, 409844f0eee88ff00398ff7f715fab053374d808c90dSteve Block FieldOperand(string, String::kLengthOffset)); 4099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ leap(string, 4100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldOperand(string, SeqOneByteString::kHeaderSize)); 410144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CopyBytes(result_pos, string, string_length); 410244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ incq(index); 410344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(not_equal, &loop_3); // Loop while (index < 0). 410444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 410544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&done); 4106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, result_operand); 410744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 410844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&return_result); 410944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Drop temp values from the stack, and restore context register. 4110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(rsp, Immediate(3 * kPointerSize)); 4111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 4112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(rax); 4113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { 4117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->arguments()->length() == 0); 4118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference debug_is_active = 4119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::debug_is_active_address(isolate()); 4120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(kScratchRegister, debug_is_active); 4121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movzxbp(rax, Operand(kScratchRegister, 0)); 4122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Integer32ToSmi(rax, rax); 412344f0eee88ff00398ff7f715fab053374d808c90dSteve Block context()->Plug(rax); 41248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang} 41258a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 41268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 4127d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 4128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->function() != NULL && 4129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch expr->function()->intrinsic_type == Runtime::INLINE) { 4130f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ InlineRuntimeCall"); 4131f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke EmitInlineRuntimeCall(expr); 4132f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return; 4133f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 4134f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 41353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block Comment cmnt(masm_, "[ CallRuntime"); 41363ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block ZoneList<Expression*>* args = expr->arguments(); 4137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int arg_count = args->length(); 41383ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4139d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (expr->is_jsruntime()) { 4140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the builtins object as receiver. 4141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, GlobalObjectOperand()); 4142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(FieldOperand(rax, GlobalObject::kBuiltinsOffset)); 4143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the function from the receiver. 4145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0)); 4146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(LoadDescriptor::NameRegister(), expr->name()); 4147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 4148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(VectorLoadICDescriptor::SlotRegister(), 4149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(expr->CallRuntimeFeedbackSlot())); 4150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(NOT_CONTEXTUAL); 4151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); 4153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 41543ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the target function under the receiver. 4156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Operand(rsp, 0)); 4157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rsp, kPointerSize), rax); 4158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the arguments ("left-to-right"). 4160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < arg_count; i++) { 4161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(i)); 4162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Record source position of the IC call. 4165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetSourcePosition(expr->position()); 4166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS); 4167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); 4168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallStub(&stub); 4169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Restore context register. 4171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 4172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->DropAndPlug(1, rax); 4173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 4175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the arguments ("left-to-right"). 4176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < arg_count; i++) { 4177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(args->at(i)); 4178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Call the C runtime. 4181d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(expr->function(), arg_count); 4182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch context()->Plug(rax); 4183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 4184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 4185d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4187d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 4188d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block switch (expr->op()) { 4189f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke case Token::DELETE: { 4190f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); 4191589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Property* property = expr->expression()->AsProperty(); 4192589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VariableProxy* proxy = expr->expression()->AsVariableProxy(); 4193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4194589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (property != NULL) { 4195589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VisitForStackValue(property->obj()); 4196589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VisitForStackValue(property->key()); 4197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Smi::FromInt(strict_mode())); 419869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 419969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch context()->Plug(rax); 4200589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (proxy != NULL) { 4201589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* var = proxy->var(); 4202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Delete of an unqualified identifier is disallowed in strict mode 4203589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // but "delete this" is allowed. 4204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(strict_mode() == SLOPPY || var->is_this()); 4205589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsUnallocated()) { 4206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(GlobalObjectOperand()); 4207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Push(var->name()); 4208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Smi::FromInt(SLOPPY)); 4209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 4210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch context()->Plug(rax); 4211589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (var->IsStackAllocated() || var->IsContextSlot()) { 4212589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Result of deleting non-global variables is false. 'this' is 4213589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // not really a variable, though we implement it as one. The 4214589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // subexpression does not have side effects. 4215589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch context()->Plug(var->is_this()); 4216e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 4217e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Non-global variable. Call the runtime to try to delete from the 4218e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // context where the variable was introduced. 4219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(context_register()); 4220e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Push(var->name()); 4221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kDeleteLookupSlot, 2); 4222e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch context()->Plug(rax); 4223e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 42241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 4225e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Result of deleting non-property, non-variable reference is true. 4226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The subexpression may have side effects. 4227e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitForEffect(expr->expression()); 4228e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch context()->Plug(true); 4229f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 4230f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke break; 4231f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 4232f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 4233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::VOID: { 4234d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (VOID)"); 4235e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke VisitForEffect(expr->expression()); 42360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(Heap::kUndefinedValueRootIndex); 4237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4238d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 4239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4240d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::NOT: { 4241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 4242e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (context()->IsEffect()) { 4243e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Unary NOT has no side effects so it's only necessary to visit the 4244e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // subexpression. Match the optimizing compiler by not branching. 4245e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitForEffect(expr->expression()); 42463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (context()->IsTest()) { 42473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const TestContext* test = TestContext::cast(context()); 42483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The labels are swapped for the recursive call. 42493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForControl(expr->expression(), 42503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test->false_label(), 42513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test->true_label(), 42523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch test->fall_through()); 42533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(test->true_label(), test->false_label()); 4254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 42553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We handle value contexts explicitly rather than simply visiting 42563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // for control and plugging the control flow into the context, 42573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // because we need to prepare a pair of extra administrative AST ids 42583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // for the optimizing compiler. 4259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue()); 42603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label materialize_true, materialize_false, done; 42613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForControl(expr->expression(), 42623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &materialize_false, 42633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &materialize_true, 42643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &materialize_true); 42653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&materialize_true); 42663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS); 42673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (context()->IsAccumulatorValue()) { 42683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(rax, Heap::kTrueValueRootIndex); 42693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 42703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PushRoot(Heap::kTrueValueRootIndex); 42713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 42723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&done, Label::kNear); 42733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&materialize_false); 42743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS); 42753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (context()->IsAccumulatorValue()) { 42763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(rax, Heap::kFalseValueRootIndex); 42773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 42783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PushRoot(Heap::kFalseValueRootIndex); 42793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 42803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&done); 4281e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 4282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 4284d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::TYPEOF: { 4286d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 42870d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { StackValueContext context(this); 42880d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForTypeofValue(expr->expression()); 42890d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 4290d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallRuntime(Runtime::kTypeof, 1); 42910d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 4292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4293d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 4294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: 4296d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNREACHABLE(); 42973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 42983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 42993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 43003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4301d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCountOperation(CountOperation* expr) { 4302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->expression()->IsValidReferenceExpression()); 4303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4304e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Comment cmnt(masm_, "[ CountOperation"); 430580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen SetSourcePosition(expr->position()); 4306e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4307e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Expression can only be a property, a global or a (parameter or local) 43083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // slot. 4309e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 4310e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke LhsKind assign_type = VARIABLE; 4311e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Property* prop = expr->expression()->AsProperty(); 4312e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // In case of a property we use the uninitialized expression context 4313e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // of the key to detect a named property. 4314e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (prop != NULL) { 4315e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke assign_type = 4316e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke (prop->key()->IsPropertyName()) ? NAMED_PROPERTY : KEYED_PROPERTY; 4317e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4318e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4319e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Evaluate expression and get value. 4320e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == VARIABLE) { 4321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(expr->expression()->AsVariableProxy()->var() != NULL); 43220d5e116f6aee03185f237311a943491bb079a768Kristian Monsen AccumulatorValueContext context(this); 43233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch EmitVariableLoad(expr->expression()->AsVariableProxy()); 4324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 4325e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Reserve space for result of postfix operation. 43260d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (expr->is_postfix() && !context()->IsEffect()) { 4327e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Push(Smi::FromInt(0)); 4328e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4329e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (assign_type == NAMED_PROPERTY) { 4330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(prop->obj()); 4331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0)); 4332e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitNamedPropertyLoad(prop); 4333e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 43343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForStackValue(prop->obj()); 4335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch VisitForStackValue(prop->key()); 4336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Leave receiver on stack 4337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, kPointerSize)); 4338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Copy of key, needed for later store. 4339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(LoadDescriptor::NameRegister(), Operand(rsp, 0)); 4340e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitKeyedPropertyLoad(prop); 4341e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4342e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4343e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4344086aeeaae12517475c22695a200be45495516549Ben Murdoch // We need a second deoptimization point after loading the value 4345086aeeaae12517475c22695a200be45495516549Ben Murdoch // in case evaluating the property load my have a side effect. 43468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (assign_type == VARIABLE) { 43478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PrepareForBailout(expr->expression(), TOS_REG); 43488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 4349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrepareForBailoutForId(prop->LoadId(), TOS_REG); 4350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Inline smi case if we are in a loop. 4353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done, stub_call; 4354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JumpPatchSite patch_site(masm_); 4355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (ShouldInlineSmiCase(expr->op())) { 4356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow; 4357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patch_site.EmitJumpIfNotSmi(rax, &slow, Label::kNear); 4358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save result for postfix expressions. 4360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->is_postfix()) { 4361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!context()->IsEffect()) { 4362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save the result on the stack. If we have a named or keyed property 4363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // we store the result under the receiver that is currently on top 4364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of the stack. 4365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (assign_type) { 4366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case VARIABLE: 4367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); 4368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case NAMED_PROPERTY: 4370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rsp, kPointerSize), rax); 4371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case KEYED_PROPERTY: 4373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rsp, 2 * kPointerSize), rax); 4374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SmiOperationExecutionMode mode; 4380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mode.Add(PRESERVE_SOURCE_REGISTER); 4381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mode.Add(BAILOUT_ON_NO_OVERFLOW); 4382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (expr->op() == Token::INC) { 4383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiAddConstant(rax, rax, Smi::FromInt(1), mode, &done, Label::kNear); 4384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 4385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiSubConstant(rax, rax, Smi::FromInt(1), mode, &done, Label::kNear); 4386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&stub_call, Label::kNear); 4388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&slow); 43898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 4390086aeeaae12517475c22695a200be45495516549Ben Murdoch 4391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ToNumberStub convert_stub(isolate()); 43921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ CallStub(&convert_stub); 4393e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4394e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Save result for postfix expressions. 4395e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 43960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 43970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // Save the result on the stack. If we have a named or keyed property 43980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // we store the result under the receiver that is currently on top 43990d5e116f6aee03185f237311a943491bb079a768Kristian Monsen // of the stack. 44000d5e116f6aee03185f237311a943491bb079a768Kristian Monsen switch (assign_type) { 44010d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case VARIABLE: 4402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rax); 44030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 44040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case NAMED_PROPERTY: 4405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rsp, kPointerSize), rax); 44060d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 44070d5e116f6aee03185f237311a943491bb079a768Kristian Monsen case KEYED_PROPERTY: 4408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rsp, 2 * kPointerSize), rax); 44090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen break; 44100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 4411e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4412e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4413e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Record position before stub call. 4415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetSourcePosition(expr->position()); 4416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4417e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Call stub for +1/-1. 4418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&stub_call); 4419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, rax); 4420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(rax, Smi::FromInt(1)); 4421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), expr->binary_op(), 4422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NO_OVERWRITE).code(); 4423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(code, expr->CountBinOpFeedbackId()); 44243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 4425d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ bind(&done); 4426e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4427e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store the value returned in rax. 4428e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke switch (assign_type) { 4429e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case VARIABLE: 4430e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 4431f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment as if via '='. 44320d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { EffectContext context(this); 44330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 44340d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Token::ASSIGN); 4435086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context.Plug(rax); 44370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 4438e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // For all contexts except kEffect: We have the result on 4439e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // top of the stack. 44400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 44410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 4442e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4443e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 4444f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Perform the assignment as if via '='. 4445e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 44460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen Token::ASSIGN); 4447086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context()->Plug(rax); 4449e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4450e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 4451e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case NAMED_PROPERTY: { 4452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(StoreDescriptor::NameRegister(), 4453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch prop->key()->AsLiteral()->value()); 4454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(StoreDescriptor::ReceiverRegister()); 4455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallStoreIC(expr->CountStoreFeedbackId()); 4456086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4457e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 44580d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 44590d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 4460e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4461e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 44620d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 4463e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4464e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 4465e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4466e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case KEYED_PROPERTY: { 4467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(StoreDescriptor::NameRegister()); 4468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(StoreDescriptor::ReceiverRegister()); 4469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = 4470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code(); 4471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, expr->CountStoreFeedbackId()); 4472086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4473e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (expr->is_postfix()) { 44740d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (!context()->IsEffect()) { 44750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PlugTOS(); 4476e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4477e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 44780d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 4479e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4480e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke break; 4481e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4482e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 4483e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 4484e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4485d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 44860d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid FullCodeGenerator::VisitForTypeofValue(Expression* expr) { 448780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen VariableProxy* proxy = expr->AsVariableProxy(); 4488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!context()->IsEffect()); 4489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!context()->IsTest()); 44900d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4491589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (proxy != NULL && proxy->var()->IsUnallocated()) { 4492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Global variable"); 4493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(LoadDescriptor::NameRegister(), proxy->name()); 4494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand()); 4495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_vector_ics) { 4496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Move(VectorLoadICDescriptor::SlotRegister(), 4497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Smi::FromInt(proxy->VariableFeedbackSlot())); 4498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 449980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Use a regular load, not a contextual load, to avoid a reference 450080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // error. 4501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallLoadIC(NOT_CONTEXTUAL); 4502086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailout(expr, TOS_REG); 45030d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 4504589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { 4505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Comment cmnt(masm_, "[ Lookup slot"); 450659151504615d929945dc59db37bf1166937748c6Steve Block Label done, slow; 450759151504615d929945dc59db37bf1166937748c6Steve Block 450859151504615d929945dc59db37bf1166937748c6Steve Block // Generate code for loading from variables potentially shadowed 450959151504615d929945dc59db37bf1166937748c6Steve Block // by eval-introduced variables. 4510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EmitDynamicLookupFastCase(proxy, INSIDE_TYPEOF, &slow, &done); 451159151504615d929945dc59db37bf1166937748c6Steve Block 451259151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&slow); 4513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rsi); 451480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ Push(proxy->name()); 4515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2); 4516086aeeaae12517475c22695a200be45495516549Ben Murdoch PrepareForBailout(expr, TOS_REG); 451759151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&done); 451859151504615d929945dc59db37bf1166937748c6Steve Block 45190d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 4520f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 452180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // This expression cannot throw a reference error at the top level. 45223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitInDuplicateContext(expr); 452380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 452480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 452580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 452680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 45273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr, 45283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Expression* sub_expr, 45293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> check) { 45303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label materialize_true, materialize_false; 45313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* if_true = NULL; 45323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* if_false = NULL; 45333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* fall_through = NULL; 45343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->PrepareTest(&materialize_true, &materialize_false, 45353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &if_true, &if_false, &fall_through); 45363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 45370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen { AccumulatorValueContext context(this); 45383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForTypeofValue(sub_expr); 45390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 45403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 45410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Factory* factory = isolate()->factory(); 4543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (String::Equals(check, factory->number_string())) { 4544e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(rax, if_true); 4545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset)); 454680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex); 454780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 4548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->string_string())) { 4549e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(rax, if_false); 455080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for undetectable objects => false. 4551e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx); 4552e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ j(above_equal, if_false); 455380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ testb(FieldOperand(rdx, Map::kBitFieldOffset), 455480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Immediate(1 << Map::kIsUndetectable)); 4555e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Split(zero, if_true, if_false, fall_through); 4556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->symbol_string())) { 4557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(rax, if_false); 4558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CmpObjectType(rax, SYMBOL_TYPE, rdx); 4559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Split(equal, if_true, if_false, fall_through); 4560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->boolean_string())) { 456180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CompareRoot(rax, Heap::kTrueValueRootIndex); 4562f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 456380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CompareRoot(rax, Heap::kFalseValueRootIndex); 456480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 4565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->undefined_string())) { 456680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 4567f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke __ j(equal, if_true); 4568e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(rax, if_false); 456980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for undetectable objects => true. 4570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rdx, FieldOperand(rax, HeapObject::kMapOffset)); 457180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ testb(FieldOperand(rdx, Map::kBitFieldOffset), 457280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Immediate(1 << Map::kIsUndetectable)); 457380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(not_zero, if_true, if_false, fall_through); 4574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->function_string())) { 4575e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(rax, if_false); 45763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); 45773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpObjectType(rax, JS_FUNCTION_TYPE, rdx); 45783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, if_true); 45793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CmpInstanceType(rdx, JS_FUNCTION_PROXY_TYPE); 45803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Split(equal, if_true, if_false, fall_through); 4581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else if (String::Equals(check, factory->object_string())) { 4582e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ JumpIfSmi(rax, if_false); 4583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(rax, Heap::kNullValueRootIndex); 4584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, if_true); 45853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpObjectType(rax, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, rdx); 4586e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ j(below, if_false); 45873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpInstanceType(rdx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); 45883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(above, if_false); 458980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Check for undetectable objects => false. 459080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ testb(FieldOperand(rdx, Map::kBitFieldOffset), 4591f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Immediate(1 << Map::kIsUndetectable)); 4592e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Split(zero, if_true, if_false, fall_through); 459380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 459480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen if (if_false != fall_through) __ jmp(if_false); 4595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 45963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context()->Plug(if_true, if_false); 4597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 4598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 4599f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 4600d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 4601d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Comment cmnt(masm_, "[ CompareOperation"); 460280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen SetSourcePosition(expr->position()); 4603e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 46043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // First we try a fast inlined version of the compare when one of 46053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the operands is a literal. 46063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (TryLiteralCompare(expr)) return; 46073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4608e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Always perform the comparison for its control flow. Pack the result 4609e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // into the expression's context after the comparison is performed. 4610f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label materialize_true, materialize_false; 4611f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_true = NULL; 4612f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Label* if_false = NULL; 461380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 46140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 46150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 461680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 46173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Token::Value op = expr->op(); 46180d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->left()); 461980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen switch (op) { 4620e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case Token::IN: 46210d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->right()); 4622d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 46233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, false, NULL, NULL); 4624d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CompareRoot(rax, Heap::kTrueValueRootIndex); 462580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 4626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 46273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4628d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block case Token::INSTANCEOF: { 46290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForStackValue(expr->right()); 4630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch InstanceofStub stub(isolate(), InstanceofStub::kNoFlags); 4631d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ CallStub(&stub); 46323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testp(rax, rax); 463480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // The stub returns 0 for true. 463580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(zero, if_true, if_false, fall_through); 4636d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 4637d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 4638d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4639d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block default: { 46400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen VisitForAccumulatorValue(expr->right()); 4641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Condition cc = CompareIC::ComputeCondition(op); 4642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rdx); 4643d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 46440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen bool inline_smi_code = ShouldInlineSmiCase(op); 46451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block JumpPatchSite patch_site(masm_); 46460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen if (inline_smi_code) { 4647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label slow_case; 4648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rcx, rdx); 4649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ orp(rcx, rax); 4650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear); 4651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmpp(rdx, rax); 465280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(cc, if_true, if_false, NULL); 465380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&slow_case); 465480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 4655d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 46561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Record position and call the compare IC. 46571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block SetSourcePosition(expr->position()); 4658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code(); 4659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, expr->CompareOperationFeedbackId()); 46603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch patch_site.EmitPatchInfo(); 4661086aeeaae12517475c22695a200be45495516549Ben Murdoch 46623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testp(rax, rax); 466480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(cc, if_true, if_false, fall_through); 4665d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 46663ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 46673ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4668e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Convert the result of the comparison into one expected for this 4669e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // expression's context. 46700d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 4671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 4672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4673d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 46743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr, 46753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Expression* sub_expr, 46763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch NilValue nil) { 467780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label materialize_true, materialize_false; 467880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_true = NULL; 467980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* if_false = NULL; 468080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label* fall_through = NULL; 46810d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->PrepareTest(&materialize_true, &materialize_false, 46820d5e116f6aee03185f237311a943491bb079a768Kristian Monsen &if_true, &if_false, &fall_through); 468380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 46843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VisitForAccumulatorValue(sub_expr); 46853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 46863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (expr->op() == Token::EQ_STRICT) { 4687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::RootListIndex nil_value = nil == kNullValue ? 4688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::kNullValueRootIndex : 4689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::kUndefinedValueRootIndex; 4690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(rax, nil_value); 469180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(equal, if_true, if_false, fall_through); 469280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 4693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); 4694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CallIC(ic, expr->CompareOperationFeedbackId()); 4695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ testp(rax, rax); 469680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Split(not_zero, if_true, if_false, fall_through); 469780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 46980d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(if_true, if_false); 469980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 470080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 470180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 4702d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { 4703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 47040d5e116f6aee03185f237311a943491bb079a768Kristian Monsen context()->Plug(rax); 4705e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 4706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 47080d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::result_register() { 47090d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return rax; 47100d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 4711d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4712e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 47130d5e116f6aee03185f237311a943491bb079a768Kristian MonsenRegister FullCodeGenerator::context_register() { 47140d5e116f6aee03185f237311a943491bb079a768Kristian Monsen return rsi; 47150d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 47160d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 47170d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 4718d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 4719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsAligned(frame_offset, kPointerSize)); 4720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rbp, frame_offset), value); 47213ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 47223ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 47233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 4724d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::LoadContextField(Register dst, int context_index) { 4725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(dst, ContextOperand(rsi, context_index)); 4726e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 4727e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4728e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 47293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid FullCodeGenerator::PushFunctionArgumentForContextAllocation() { 47303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Scope* declaration_scope = scope()->DeclarationScope(); 4731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (declaration_scope->is_global_scope() || 4732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch declaration_scope->is_module_scope()) { 4733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Contexts nested in the native context have a canonical empty function 47343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // as their closure, not the anonymous closure containing the global 47353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // code. Pass a smi sentinel and let the runtime look up the empty 47363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // function. 47373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Push(Smi::FromInt(0)); 47383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else if (declaration_scope->is_eval_scope()) { 47393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Contexts created by a call to eval have the same closure as the 47403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // context calling eval, not the anonymous closure containing the eval 47413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // code. Fetch it from the context. 4742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(ContextOperand(rsi, Context::CLOSURE_INDEX)); 47433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 4744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(declaration_scope->is_function_scope()); 4745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 47463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 47473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 47483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 47493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4750e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// ---------------------------------------------------------------------------- 4751e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Non-local control flow support. 4752e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4753e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4754d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::EnterFinallyBlock() { 4755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!result_register().is(rdx)); 4756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!result_register().is(rcx)); 4757e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Cook return address on top of stack (smi encoded Code* delta) 4758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PopReturnAddressTo(rdx); 4759e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(rcx, masm_->CodeObject()); 4760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ subp(rdx, rcx); 4761e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Integer32ToSmi(rdx, rdx); 4762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdx); 4763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4764e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store result register while executing finally block. 4765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(result_register()); 4766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store pending message while executing finally block. 4768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference pending_message_obj = 4769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_pending_message_obj(isolate()); 4770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Load(rdx, pending_message_obj); 4771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdx); 4772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference has_pending_message = 4774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_has_pending_message(isolate()); 4775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Load(rdx, has_pending_message); 4776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Integer32ToSmi(rdx, rdx); 4777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdx); 4778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference pending_message_script = 4780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_pending_message_script(isolate()); 4781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Load(rdx, pending_message_script); 4782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(rdx); 4783e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke} 4784e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4785e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 4786d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid FullCodeGenerator::ExitFinallyBlock() { 4787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!result_register().is(rdx)); 4788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!result_register().is(rcx)); 4789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore pending message from stack. 4790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rdx); 4791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference pending_message_script = 4792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_pending_message_script(isolate()); 4793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Store(pending_message_script, rdx); 4794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rdx); 4796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiToInteger32(rdx, rdx); 4797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference has_pending_message = 4798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_has_pending_message(isolate()); 4799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Store(has_pending_message, rdx); 4800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rdx); 4802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference pending_message_obj = 4803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::address_of_pending_message_obj(isolate()); 4804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Store(pending_message_obj, rdx); 4805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore result register from stack. 4807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(result_register()); 4808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4809e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Uncook return address. 4810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Pop(rdx); 4811e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ SmiToInteger32(rdx, rdx); 4812e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ Move(rcx, masm_->CodeObject()); 4813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addp(rdx, rcx); 48143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(rdx); 4815d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 4816d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4817d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4818d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#undef __ 4819d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 482069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#define __ ACCESS_MASM(masm()) 482169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 482269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochFullCodeGenerator::NestedStatement* FullCodeGenerator::TryFinally::Exit( 482369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int* stack_depth, 482469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int* context_length) { 482569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // The macros used here must preserve the result register. 482669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 482769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Because the handler block contains the context of the finally 482869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // code, we can restore it directly from there for the finally code 482969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // rather than iteratively unwinding contexts via their previous 483069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // links. 483169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Drop(*stack_depth); // Down to the handler block. 483269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (*context_length > 0) { 483369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Restore the context to its dedicated register and the stack. 4834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(rsi, Operand(rsp, StackHandlerConstants::kContextOffset)); 4835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); 483669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 483769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ PopTryHandler(); 483869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ call(finally_entry_); 483969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 484069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch *stack_depth = 0; 484169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch *context_length = 0; 484269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch return previous_; 484369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch} 484469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 484569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 484669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#undef __ 4847d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const byte kJnsInstruction = 0x79; 4850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const byte kNopByteOne = 0x66; 4851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const byte kNopByteTwo = 0x90; 4852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG 4853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const byte kCallInstruction = 0xe8; 4854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 4855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid BackEdgeTable::PatchAt(Code* unoptimized_code, 4858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address pc, 4859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch BackEdgeState target_state, 4860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code* replacement_code) { 4861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address call_target_address = pc - kIntSize; 4862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address jns_instr_address = call_target_address - 3; 4863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address jns_offset_address = call_target_address - 2; 4864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (target_state) { 4866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case INTERRUPT: 4867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // sub <profiling_counter>, <delta> ;; Not changed 4868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // jns ok 4869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // call <interrupt stub> 4870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ok: 4871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *jns_instr_address = kJnsInstruction; 4872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *jns_offset_address = kJnsOffset; 4873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case ON_STACK_REPLACEMENT: 4875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case OSR_AFTER_STACK_CHECK: 4876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // sub <profiling_counter>, <delta> ;; Not changed 4877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // nop 4878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // nop 4879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // call <on-stack replacment> 4880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ok: 4881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *jns_instr_address = kNopByteOne; 4882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch *jns_offset_address = kNopByteTwo; 4883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch break; 4884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::set_target_address_at(call_target_address, 4887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unoptimized_code, 4888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch replacement_code->entry()); 4889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch( 4890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unoptimized_code, call_target_address, replacement_code); 4891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochBackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( 4895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate, 4896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code* unoptimized_code, 4897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address pc) { 4898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address call_target_address = pc - kIntSize; 4899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address jns_instr_address = call_target_address - 3; 4900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(kCallInstruction, *(call_target_address - 1)); 4901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (*jns_instr_address == kJnsInstruction) { 4903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(kJnsOffset, *(call_target_address - 2)); 4904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(isolate->builtins()->InterruptCheck()->entry(), 4905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::target_address_at(call_target_address, 4906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unoptimized_code)); 4907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return INTERRUPT; 4908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(kNopByteOne, *jns_instr_address); 4911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(kNopByteTwo, *(call_target_address - 2)); 4912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (Assembler::target_address_at(call_target_address, 4914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unoptimized_code) == 4915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate->builtins()->OnStackReplacement()->entry()) { 4916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ON_STACK_REPLACEMENT; 4917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 4918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), 4920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::target_address_at(call_target_address, 4921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch unoptimized_code)); 4922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return OSR_AFTER_STACK_CHECK; 4923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 4924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 4925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 49263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} } // namespace v8::internal 4927f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 4928f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_X64 4929