Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(82)

Side by Side Diff: src/x64/codegen-x64.cc

Issue 6685088: Merge isolates to bleeding_edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/codegen-x64.h ('k') | src/x64/cpu-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 RegisterAllocator register_allocator(this); 173 RegisterAllocator register_allocator(this);
174 allocator_ = &register_allocator; 174 allocator_ = &register_allocator;
175 ASSERT(frame_ == NULL); 175 ASSERT(frame_ == NULL);
176 frame_ = new VirtualFrame(); 176 frame_ = new VirtualFrame();
177 set_in_spilled_code(false); 177 set_in_spilled_code(false);
178 178
179 // Adjust for function-level loop nesting. 179 // Adjust for function-level loop nesting.
180 ASSERT_EQ(0, loop_nesting_); 180 ASSERT_EQ(0, loop_nesting_);
181 loop_nesting_ = info->is_in_loop() ? 1 : 0; 181 loop_nesting_ = info->is_in_loop() ? 1 : 0;
182 182
183 JumpTarget::set_compiling_deferred_code(false); 183 Isolate::Current()->set_jump_target_compiling_deferred_code(false);
184 184
185 { 185 {
186 CodeGenState state(this); 186 CodeGenState state(this);
187 // Entry: 187 // Entry:
188 // Stack: receiver, arguments, return address. 188 // Stack: receiver, arguments, return address.
189 // rbp: caller's frame pointer 189 // rbp: caller's frame pointer
190 // rsp: stack pointer 190 // rsp: stack pointer
191 // rdi: called JS function 191 // rdi: called JS function
192 // rsi: callee's context 192 // rsi: callee's context
193 allocator_->Initialize(); 193 allocator_->Initialize();
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 274
275 // Store the arguments object. This must happen after context 275 // Store the arguments object. This must happen after context
276 // initialization because the arguments object may be stored in 276 // initialization because the arguments object may be stored in
277 // the context. 277 // the context.
278 if (ArgumentsMode() != NO_ARGUMENTS_ALLOCATION) { 278 if (ArgumentsMode() != NO_ARGUMENTS_ALLOCATION) {
279 StoreArgumentsObject(true); 279 StoreArgumentsObject(true);
280 } 280 }
281 281
282 // Initialize ThisFunction reference if present. 282 // Initialize ThisFunction reference if present.
283 if (scope()->is_function_scope() && scope()->function() != NULL) { 283 if (scope()->is_function_scope() && scope()->function() != NULL) {
284 frame_->Push(Factory::the_hole_value()); 284 frame_->Push(FACTORY->the_hole_value());
285 StoreToSlot(scope()->function()->AsSlot(), NOT_CONST_INIT); 285 StoreToSlot(scope()->function()->AsSlot(), NOT_CONST_INIT);
286 } 286 }
287 287
288 // Initialize the function return target after the locals are set 288 // Initialize the function return target after the locals are set
289 // up, because it needs the expected frame height from the frame. 289 // up, because it needs the expected frame height from the frame.
290 function_return_.set_direction(JumpTarget::BIDIRECTIONAL); 290 function_return_.set_direction(JumpTarget::BIDIRECTIONAL);
291 function_return_is_shadowed_ = false; 291 function_return_is_shadowed_ = false;
292 292
293 // Generate code to 'execute' declarations and initialize functions 293 // Generate code to 'execute' declarations and initialize functions
294 // (source elements). In case of an illegal redeclaration we need to 294 // (source elements). In case of an illegal redeclaration we need to
(...skipping 14 matching lines...) Expand all
309 // Ignore the return value. 309 // Ignore the return value.
310 } 310 }
311 CheckStack(); 311 CheckStack();
312 312
313 // Compile the body of the function in a vanilla state. Don't 313 // Compile the body of the function in a vanilla state. Don't
314 // bother compiling all the code if the scope has an illegal 314 // bother compiling all the code if the scope has an illegal
315 // redeclaration. 315 // redeclaration.
316 if (!scope()->HasIllegalRedeclaration()) { 316 if (!scope()->HasIllegalRedeclaration()) {
317 Comment cmnt(masm_, "[ function body"); 317 Comment cmnt(masm_, "[ function body");
318 #ifdef DEBUG 318 #ifdef DEBUG
319 bool is_builtin = Bootstrapper::IsActive(); 319 bool is_builtin = Isolate::Current()->bootstrapper()->IsActive();
320 bool should_trace = 320 bool should_trace =
321 is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls; 321 is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls;
322 if (should_trace) { 322 if (should_trace) {
323 frame_->CallRuntime(Runtime::kDebugTrace, 0); 323 frame_->CallRuntime(Runtime::kDebugTrace, 0);
324 // Ignore the return value. 324 // Ignore the return value.
325 } 325 }
326 #endif 326 #endif
327 VisitStatements(info->function()->body()); 327 VisitStatements(info->function()->body());
328 328
329 // Handle the return from the function. 329 // Handle the return from the function.
330 if (has_valid_frame()) { 330 if (has_valid_frame()) {
331 // If there is a valid frame, control flow can fall off the end of 331 // If there is a valid frame, control flow can fall off the end of
332 // the body. In that case there is an implicit return statement. 332 // the body. In that case there is an implicit return statement.
333 ASSERT(!function_return_is_shadowed_); 333 ASSERT(!function_return_is_shadowed_);
334 CodeForReturnPosition(info->function()); 334 CodeForReturnPosition(info->function());
335 frame_->PrepareForReturn(); 335 frame_->PrepareForReturn();
336 Result undefined(Factory::undefined_value()); 336 Result undefined(FACTORY->undefined_value());
337 if (function_return_.is_bound()) { 337 if (function_return_.is_bound()) {
338 function_return_.Jump(&undefined); 338 function_return_.Jump(&undefined);
339 } else { 339 } else {
340 function_return_.Bind(&undefined); 340 function_return_.Bind(&undefined);
341 GenerateReturnSequence(&undefined); 341 GenerateReturnSequence(&undefined);
342 } 342 }
343 } else if (function_return_.is_linked()) { 343 } else if (function_return_.is_linked()) {
344 // If the return target has dangling jumps to it, then we have not 344 // If the return target has dangling jumps to it, then we have not
345 // yet generated the return sequence. This can happen when (a) 345 // yet generated the return sequence. This can happen when (a)
346 // control does not flow off the end of the body so we did not 346 // control does not flow off the end of the body so we did not
(...skipping 11 matching lines...) Expand all
358 loop_nesting_ = 0; 358 loop_nesting_ = 0;
359 359
360 // Code generation state must be reset. 360 // Code generation state must be reset.
361 ASSERT(state_ == NULL); 361 ASSERT(state_ == NULL);
362 ASSERT(!function_return_is_shadowed_); 362 ASSERT(!function_return_is_shadowed_);
363 function_return_.Unuse(); 363 function_return_.Unuse();
364 DeleteFrame(); 364 DeleteFrame();
365 365
366 // Process any deferred code using the register allocator. 366 // Process any deferred code using the register allocator.
367 if (!HasStackOverflow()) { 367 if (!HasStackOverflow()) {
368 JumpTarget::set_compiling_deferred_code(true); 368 info->isolate()->set_jump_target_compiling_deferred_code(true);
369 ProcessDeferred(); 369 ProcessDeferred();
370 JumpTarget::set_compiling_deferred_code(false); 370 info->isolate()->set_jump_target_compiling_deferred_code(false);
371 } 371 }
372 372
373 // There is no need to delete the register allocator, it is a 373 // There is no need to delete the register allocator, it is a
374 // stack-allocated local. 374 // stack-allocated local.
375 allocator_ = NULL; 375 allocator_ = NULL;
376 } 376 }
377 377
378 378
379 Operand CodeGenerator::SlotOperand(Slot* slot, Register tmp) { 379 Operand CodeGenerator::SlotOperand(Slot* slot, Register tmp) {
380 // Currently, this assertion will fail if we try to assign to 380 // Currently, this assertion will fail if we try to assign to
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
509 #endif 509 #endif
510 ASSERT(!in_spilled_code()); 510 ASSERT(!in_spilled_code());
511 JumpTarget true_target; 511 JumpTarget true_target;
512 JumpTarget false_target; 512 JumpTarget false_target;
513 ControlDestination dest(&true_target, &false_target, true); 513 ControlDestination dest(&true_target, &false_target, true);
514 LoadCondition(expr, &dest, false); 514 LoadCondition(expr, &dest, false);
515 515
516 if (dest.false_was_fall_through()) { 516 if (dest.false_was_fall_through()) {
517 // The false target was just bound. 517 // The false target was just bound.
518 JumpTarget loaded; 518 JumpTarget loaded;
519 frame_->Push(Factory::false_value()); 519 frame_->Push(FACTORY->false_value());
520 // There may be dangling jumps to the true target. 520 // There may be dangling jumps to the true target.
521 if (true_target.is_linked()) { 521 if (true_target.is_linked()) {
522 loaded.Jump(); 522 loaded.Jump();
523 true_target.Bind(); 523 true_target.Bind();
524 frame_->Push(Factory::true_value()); 524 frame_->Push(FACTORY->true_value());
525 loaded.Bind(); 525 loaded.Bind();
526 } 526 }
527 527
528 } else if (dest.is_used()) { 528 } else if (dest.is_used()) {
529 // There is true, and possibly false, control flow (with true as 529 // There is true, and possibly false, control flow (with true as
530 // the fall through). 530 // the fall through).
531 JumpTarget loaded; 531 JumpTarget loaded;
532 frame_->Push(Factory::true_value()); 532 frame_->Push(FACTORY->true_value());
533 if (false_target.is_linked()) { 533 if (false_target.is_linked()) {
534 loaded.Jump(); 534 loaded.Jump();
535 false_target.Bind(); 535 false_target.Bind();
536 frame_->Push(Factory::false_value()); 536 frame_->Push(FACTORY->false_value());
537 loaded.Bind(); 537 loaded.Bind();
538 } 538 }
539 539
540 } else { 540 } else {
541 // We have a valid value on top of the frame, but we still may 541 // We have a valid value on top of the frame, but we still may
542 // have dangling jumps to the true and false targets from nested 542 // have dangling jumps to the true and false targets from nested
543 // subexpressions (eg, the left subexpressions of the 543 // subexpressions (eg, the left subexpressions of the
544 // short-circuited boolean operators). 544 // short-circuited boolean operators).
545 ASSERT(has_valid_frame()); 545 ASSERT(has_valid_frame());
546 if (true_target.is_linked() || false_target.is_linked()) { 546 if (true_target.is_linked() || false_target.is_linked()) {
547 JumpTarget loaded; 547 JumpTarget loaded;
548 loaded.Jump(); // Don't lose the current TOS. 548 loaded.Jump(); // Don't lose the current TOS.
549 if (true_target.is_linked()) { 549 if (true_target.is_linked()) {
550 true_target.Bind(); 550 true_target.Bind();
551 frame_->Push(Factory::true_value()); 551 frame_->Push(FACTORY->true_value());
552 if (false_target.is_linked()) { 552 if (false_target.is_linked()) {
553 loaded.Jump(); 553 loaded.Jump();
554 } 554 }
555 } 555 }
556 if (false_target.is_linked()) { 556 if (false_target.is_linked()) {
557 false_target.Bind(); 557 false_target.Bind();
558 frame_->Push(Factory::false_value()); 558 frame_->Push(FACTORY->false_value());
559 } 559 }
560 loaded.Bind(); 560 loaded.Bind();
561 } 561 }
562 } 562 }
563 563
564 ASSERT(has_valid_frame()); 564 ASSERT(has_valid_frame());
565 ASSERT(frame_->height() == original_height + 1); 565 ASSERT(frame_->height() == original_height + 1);
566 } 566 }
567 567
568 568
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
625 625
626 Result CodeGenerator::StoreArgumentsObject(bool initial) { 626 Result CodeGenerator::StoreArgumentsObject(bool initial) {
627 ArgumentsAllocationMode mode = ArgumentsMode(); 627 ArgumentsAllocationMode mode = ArgumentsMode();
628 ASSERT(mode != NO_ARGUMENTS_ALLOCATION); 628 ASSERT(mode != NO_ARGUMENTS_ALLOCATION);
629 629
630 Comment cmnt(masm_, "[ store arguments object"); 630 Comment cmnt(masm_, "[ store arguments object");
631 if (mode == LAZY_ARGUMENTS_ALLOCATION && initial) { 631 if (mode == LAZY_ARGUMENTS_ALLOCATION && initial) {
632 // When using lazy arguments allocation, we store the arguments marker value 632 // When using lazy arguments allocation, we store the arguments marker value
633 // as a sentinel indicating that the arguments object hasn't been 633 // as a sentinel indicating that the arguments object hasn't been
634 // allocated yet. 634 // allocated yet.
635 frame_->Push(Factory::arguments_marker()); 635 frame_->Push(FACTORY->arguments_marker());
636 } else { 636 } else {
637 ArgumentsAccessStub stub(is_strict_mode() 637 ArgumentsAccessStub stub(is_strict_mode()
638 ? ArgumentsAccessStub::NEW_STRICT 638 ? ArgumentsAccessStub::NEW_STRICT
639 : ArgumentsAccessStub::NEW_NON_STRICT); 639 : ArgumentsAccessStub::NEW_NON_STRICT);
640 frame_->PushFunction(); 640 frame_->PushFunction();
641 frame_->PushReceiverSlotAddress(); 641 frame_->PushReceiverSlotAddress();
642 frame_->Push(Smi::FromInt(scope()->num_parameters())); 642 frame_->Push(Smi::FromInt(scope()->num_parameters()));
643 Result result = frame_->CallStub(&stub, 3); 643 Result result = frame_->CallStub(&stub, 3);
644 frame_->Push(&result); 644 frame_->Push(&result);
645 } 645 }
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after
1055 answer = GenerateGenericBinaryOpStubCall(&stub, &left, &right); 1055 answer = GenerateGenericBinaryOpStubCall(&stub, &left, &right);
1056 } 1056 }
1057 } 1057 }
1058 1058
1059 answer.set_type_info(result_type); 1059 answer.set_type_info(result_type);
1060 frame_->Push(&answer); 1060 frame_->Push(&answer);
1061 } 1061 }
1062 1062
1063 1063
1064 bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) { 1064 bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) {
1065 Object* answer_object = Heap::undefined_value(); 1065 Object* answer_object = HEAP->undefined_value();
1066 switch (op) { 1066 switch (op) {
1067 case Token::ADD: 1067 case Token::ADD:
1068 // Use intptr_t to detect overflow of 32-bit int. 1068 // Use intptr_t to detect overflow of 32-bit int.
1069 if (Smi::IsValid(static_cast<intptr_t>(left) + right)) { 1069 if (Smi::IsValid(static_cast<intptr_t>(left) + right)) {
1070 answer_object = Smi::FromInt(left + right); 1070 answer_object = Smi::FromInt(left + right);
1071 } 1071 }
1072 break; 1072 break;
1073 case Token::SUB: 1073 case Token::SUB:
1074 // Use intptr_t to detect overflow of 32-bit int. 1074 // Use intptr_t to detect overflow of 32-bit int.
1075 if (Smi::IsValid(static_cast<intptr_t>(left) - right)) { 1075 if (Smi::IsValid(static_cast<intptr_t>(left) - right)) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1129 unsigned_left >>= shift_amount; 1129 unsigned_left >>= shift_amount;
1130 } 1130 }
1131 ASSERT(Smi::IsValid(static_cast<int32_t>(unsigned_left))); 1131 ASSERT(Smi::IsValid(static_cast<int32_t>(unsigned_left)));
1132 answer_object = Smi::FromInt(static_cast<int32_t>(unsigned_left)); 1132 answer_object = Smi::FromInt(static_cast<int32_t>(unsigned_left));
1133 break; 1133 break;
1134 } 1134 }
1135 default: 1135 default:
1136 UNREACHABLE(); 1136 UNREACHABLE();
1137 break; 1137 break;
1138 } 1138 }
1139 if (answer_object == Heap::undefined_value()) { 1139 if (answer_object->IsUndefined()) {
1140 return false; 1140 return false;
1141 } 1141 }
1142 frame_->Push(Handle<Object>(answer_object)); 1142 frame_->Push(Handle<Object>(answer_object));
1143 return true; 1143 return true;
1144 } 1144 }
1145 1145
1146 1146
1147 void CodeGenerator::JumpIfBothSmiUsingTypeInfo(Result* left, 1147 void CodeGenerator::JumpIfBothSmiUsingTypeInfo(Result* left,
1148 Result* right, 1148 Result* right,
1149 JumpTarget* both_smi) { 1149 JumpTarget* both_smi) {
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
1364 __ AbortIfNotSmi(right->reg()); 1364 __ AbortIfNotSmi(right->reg());
1365 } 1365 }
1366 // If left is not known to be a smi, check if it is. 1366 // If left is not known to be a smi, check if it is.
1367 // If left is not known to be a number, and it isn't a smi, check if 1367 // If left is not known to be a number, and it isn't a smi, check if
1368 // it is a HeapNumber. 1368 // it is a HeapNumber.
1369 if (!left_type_info.IsSmi()) { 1369 if (!left_type_info.IsSmi()) {
1370 __ JumpIfSmi(answer.reg(), &do_op); 1370 __ JumpIfSmi(answer.reg(), &do_op);
1371 if (!left_type_info.IsNumber()) { 1371 if (!left_type_info.IsNumber()) {
1372 // Branch if not a heapnumber. 1372 // Branch if not a heapnumber.
1373 __ Cmp(FieldOperand(answer.reg(), HeapObject::kMapOffset), 1373 __ Cmp(FieldOperand(answer.reg(), HeapObject::kMapOffset),
1374 Factory::heap_number_map()); 1374 FACTORY->heap_number_map());
1375 deferred->Branch(not_equal); 1375 deferred->Branch(not_equal);
1376 } 1376 }
1377 // Load integer value into answer register using truncation. 1377 // Load integer value into answer register using truncation.
1378 __ cvttsd2si(answer.reg(), 1378 __ cvttsd2si(answer.reg(),
1379 FieldOperand(answer.reg(), HeapNumber::kValueOffset)); 1379 FieldOperand(answer.reg(), HeapNumber::kValueOffset));
1380 // Branch if we might have overflowed. 1380 // Branch if we might have overflowed.
1381 // (False negative for Smi::kMinValue) 1381 // (False negative for Smi::kMinValue)
1382 __ cmpl(answer.reg(), Immediate(0x80000000)); 1382 __ cmpl(answer.reg(), Immediate(0x80000000));
1383 deferred->Branch(equal); 1383 deferred->Branch(equal);
1384 // TODO(lrn): Inline shifts on int32 here instead of first smi-tagging. 1384 // TODO(lrn): Inline shifts on int32 here instead of first smi-tagging.
(...skipping 941 matching lines...) Expand 10 before | Expand all | Expand 10 after
2326 } 2326 }
2327 2327
2328 // Jump or fall through to here if we are comparing a non-smi to a 2328 // Jump or fall through to here if we are comparing a non-smi to a
2329 // constant smi. If the non-smi is a heap number and this is not 2329 // constant smi. If the non-smi is a heap number and this is not
2330 // a loop condition, inline the floating point code. 2330 // a loop condition, inline the floating point code.
2331 if (!is_loop_condition) { 2331 if (!is_loop_condition) {
2332 // Right side is a constant smi and left side has been checked 2332 // Right side is a constant smi and left side has been checked
2333 // not to be a smi. 2333 // not to be a smi.
2334 JumpTarget not_number; 2334 JumpTarget not_number;
2335 __ Cmp(FieldOperand(left_reg, HeapObject::kMapOffset), 2335 __ Cmp(FieldOperand(left_reg, HeapObject::kMapOffset),
2336 Factory::heap_number_map()); 2336 FACTORY->heap_number_map());
2337 not_number.Branch(not_equal, left_side); 2337 not_number.Branch(not_equal, left_side);
2338 __ movsd(xmm1, 2338 __ movsd(xmm1,
2339 FieldOperand(left_reg, HeapNumber::kValueOffset)); 2339 FieldOperand(left_reg, HeapNumber::kValueOffset));
2340 int value = constant_smi->value(); 2340 int value = constant_smi->value();
2341 if (value == 0) { 2341 if (value == 0) {
2342 __ xorpd(xmm0, xmm0); 2342 __ xorpd(xmm0, xmm0);
2343 } else { 2343 } else {
2344 Result temp = allocator()->Allocate(); 2344 Result temp = allocator()->Allocate();
2345 __ movl(temp.reg(), Immediate(value)); 2345 __ movl(temp.reg(), Immediate(value));
2346 __ cvtlsi2sd(xmm0, temp.reg()); 2346 __ cvtlsi2sd(xmm0, temp.reg());
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
2486 // stack, as receiver and arguments, and calls x. 2486 // stack, as receiver and arguments, and calls x.
2487 // In the implementation comments, we call x the applicand 2487 // In the implementation comments, we call x the applicand
2488 // and y the receiver. 2488 // and y the receiver.
2489 ASSERT(ArgumentsMode() == LAZY_ARGUMENTS_ALLOCATION); 2489 ASSERT(ArgumentsMode() == LAZY_ARGUMENTS_ALLOCATION);
2490 ASSERT(arguments->IsArguments()); 2490 ASSERT(arguments->IsArguments());
2491 2491
2492 // Load applicand.apply onto the stack. This will usually 2492 // Load applicand.apply onto the stack. This will usually
2493 // give us a megamorphic load site. Not super, but it works. 2493 // give us a megamorphic load site. Not super, but it works.
2494 Load(applicand); 2494 Load(applicand);
2495 frame()->Dup(); 2495 frame()->Dup();
2496 Handle<String> name = Factory::LookupAsciiSymbol("apply"); 2496 Handle<String> name = FACTORY->LookupAsciiSymbol("apply");
2497 frame()->Push(name); 2497 frame()->Push(name);
2498 Result answer = frame()->CallLoadIC(RelocInfo::CODE_TARGET); 2498 Result answer = frame()->CallLoadIC(RelocInfo::CODE_TARGET);
2499 __ nop(); 2499 __ nop();
2500 frame()->Push(&answer); 2500 frame()->Push(&answer);
2501 2501
2502 // Load the receiver and the existing arguments object onto the 2502 // Load the receiver and the existing arguments object onto the
2503 // expression stack. Avoid allocating the arguments object here. 2503 // expression stack. Avoid allocating the arguments object here.
2504 Load(receiver); 2504 Load(receiver);
2505 LoadFromSlot(scope()->arguments()->AsSlot(), NOT_INSIDE_TYPEOF); 2505 LoadFromSlot(scope()->arguments()->AsSlot(), NOT_INSIDE_TYPEOF);
2506 2506
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
2554 __ j(below, &build_args); 2554 __ j(below, &build_args);
2555 2555
2556 // Check that applicand.apply is Function.prototype.apply. 2556 // Check that applicand.apply is Function.prototype.apply.
2557 __ movq(rax, Operand(rsp, kPointerSize)); 2557 __ movq(rax, Operand(rsp, kPointerSize));
2558 is_smi = masm_->CheckSmi(rax); 2558 is_smi = masm_->CheckSmi(rax);
2559 __ j(is_smi, &build_args); 2559 __ j(is_smi, &build_args);
2560 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rcx); 2560 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rcx);
2561 __ j(not_equal, &build_args); 2561 __ j(not_equal, &build_args);
2562 __ movq(rcx, FieldOperand(rax, JSFunction::kCodeEntryOffset)); 2562 __ movq(rcx, FieldOperand(rax, JSFunction::kCodeEntryOffset));
2563 __ subq(rcx, Immediate(Code::kHeaderSize - kHeapObjectTag)); 2563 __ subq(rcx, Immediate(Code::kHeaderSize - kHeapObjectTag));
2564 Handle<Code> apply_code(Builtins::builtin(Builtins::FunctionApply)); 2564 Handle<Code> apply_code(Isolate::Current()->builtins()->builtin(
2565 Builtins::FunctionApply));
2565 __ Cmp(rcx, apply_code); 2566 __ Cmp(rcx, apply_code);
2566 __ j(not_equal, &build_args); 2567 __ j(not_equal, &build_args);
2567 2568
2568 // Check that applicand is a function. 2569 // Check that applicand is a function.
2569 __ movq(rdi, Operand(rsp, 2 * kPointerSize)); 2570 __ movq(rdi, Operand(rsp, 2 * kPointerSize));
2570 is_smi = masm_->CheckSmi(rdi); 2571 is_smi = masm_->CheckSmi(rdi);
2571 __ j(is_smi, &build_args); 2572 __ j(is_smi, &build_args);
2572 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); 2573 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
2573 __ j(not_equal, &build_args); 2574 __ j(not_equal, &build_args);
2574 2575
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
2797 Result ignored = frame_->CallRuntime(Runtime::kDeclareContextSlot, 4); 2798 Result ignored = frame_->CallRuntime(Runtime::kDeclareContextSlot, 4);
2798 // Ignore the return value (declarations are statements). 2799 // Ignore the return value (declarations are statements).
2799 return; 2800 return;
2800 } 2801 }
2801 2802
2802 ASSERT(!var->is_global()); 2803 ASSERT(!var->is_global());
2803 2804
2804 // If we have a function or a constant, we need to initialize the variable. 2805 // If we have a function or a constant, we need to initialize the variable.
2805 Expression* val = NULL; 2806 Expression* val = NULL;
2806 if (node->mode() == Variable::CONST) { 2807 if (node->mode() == Variable::CONST) {
2807 val = new Literal(Factory::the_hole_value()); 2808 val = new Literal(FACTORY->the_hole_value());
2808 } else { 2809 } else {
2809 val = node->fun(); // NULL if we don't have a function 2810 val = node->fun(); // NULL if we don't have a function
2810 } 2811 }
2811 2812
2812 if (val != NULL) { 2813 if (val != NULL) {
2813 { 2814 {
2814 // Set the initial value. 2815 // Set the initial value.
2815 Reference target(this, node->proxy()); 2816 Reference target(this, node->proxy());
2816 Load(val); 2817 Load(val);
2817 target.SetValue(NOT_CONST_INIT); 2818 target.SetValue(NOT_CONST_INIT);
(...skipping 1155 matching lines...) Expand 10 before | Expand all | Expand 10 after
3973 // After shadowing stops, the original targets are unshadowed and the 3974 // After shadowing stops, the original targets are unshadowed and the
3974 // ShadowTargets represent the formerly shadowing targets. 3975 // ShadowTargets represent the formerly shadowing targets.
3975 bool has_unlinks = false; 3976 bool has_unlinks = false;
3976 for (int i = 0; i < shadows.length(); i++) { 3977 for (int i = 0; i < shadows.length(); i++) {
3977 shadows[i]->StopShadowing(); 3978 shadows[i]->StopShadowing();
3978 has_unlinks = has_unlinks || shadows[i]->is_linked(); 3979 has_unlinks = has_unlinks || shadows[i]->is_linked();
3979 } 3980 }
3980 function_return_is_shadowed_ = function_return_was_shadowed; 3981 function_return_is_shadowed_ = function_return_was_shadowed;
3981 3982
3982 // Get an external reference to the handler address. 3983 // Get an external reference to the handler address.
3983 ExternalReference handler_address(Top::k_handler_address); 3984 ExternalReference handler_address(Isolate::k_handler_address);
3984 3985
3985 // Make sure that there's nothing left on the stack above the 3986 // Make sure that there's nothing left on the stack above the
3986 // handler structure. 3987 // handler structure.
3987 if (FLAG_debug_code) { 3988 if (FLAG_debug_code) {
3988 __ movq(kScratchRegister, handler_address); 3989 __ movq(kScratchRegister, handler_address);
3989 __ cmpq(rsp, Operand(kScratchRegister, 0)); 3990 __ cmpq(rsp, Operand(kScratchRegister, 0));
3990 __ Assert(equal, "stack pointer should point to top handler"); 3991 __ Assert(equal, "stack pointer should point to top handler");
3991 } 3992 }
3992 3993
3993 // If we can fall off the end of the try block, unlink from try chain. 3994 // If we can fall off the end of the try block, unlink from try chain.
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
4102 // After shadowing stops, the original targets are unshadowed and the 4103 // After shadowing stops, the original targets are unshadowed and the
4103 // ShadowTargets represent the formerly shadowing targets. 4104 // ShadowTargets represent the formerly shadowing targets.
4104 int nof_unlinks = 0; 4105 int nof_unlinks = 0;
4105 for (int i = 0; i < shadows.length(); i++) { 4106 for (int i = 0; i < shadows.length(); i++) {
4106 shadows[i]->StopShadowing(); 4107 shadows[i]->StopShadowing();
4107 if (shadows[i]->is_linked()) nof_unlinks++; 4108 if (shadows[i]->is_linked()) nof_unlinks++;
4108 } 4109 }
4109 function_return_is_shadowed_ = function_return_was_shadowed; 4110 function_return_is_shadowed_ = function_return_was_shadowed;
4110 4111
4111 // Get an external reference to the handler address. 4112 // Get an external reference to the handler address.
4112 ExternalReference handler_address(Top::k_handler_address); 4113 ExternalReference handler_address(Isolate::k_handler_address);
4113 4114
4114 // If we can fall off the end of the try block, unlink from the try 4115 // If we can fall off the end of the try block, unlink from the try
4115 // chain and set the state on the frame to FALLING. 4116 // chain and set the state on the frame to FALLING.
4116 if (has_valid_frame()) { 4117 if (has_valid_frame()) {
4117 // The next handler address is on top of the frame. 4118 // The next handler address is on top of the frame.
4118 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0); 4119 STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
4119 __ movq(kScratchRegister, handler_address); 4120 __ movq(kScratchRegister, handler_address);
4120 frame_->EmitPop(Operand(kScratchRegister, 0)); 4121 frame_->EmitPop(Operand(kScratchRegister, 0));
4121 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1); 4122 frame_->Drop(StackHandlerConstants::kSize / kPointerSize - 1);
4122 4123
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
4269 function_info->strict_mode() ? kStrictMode : kNonStrictMode); 4270 function_info->strict_mode() ? kStrictMode : kNonStrictMode);
4270 frame_->Push(function_info); 4271 frame_->Push(function_info);
4271 Result answer = frame_->CallStub(&stub, 1); 4272 Result answer = frame_->CallStub(&stub, 1);
4272 frame_->Push(&answer); 4273 frame_->Push(&answer);
4273 } else { 4274 } else {
4274 // Call the runtime to instantiate the function based on the 4275 // Call the runtime to instantiate the function based on the
4275 // shared function info. 4276 // shared function info.
4276 frame_->EmitPush(rsi); 4277 frame_->EmitPush(rsi);
4277 frame_->EmitPush(function_info); 4278 frame_->EmitPush(function_info);
4278 frame_->EmitPush(pretenure 4279 frame_->EmitPush(pretenure
4279 ? Factory::true_value() 4280 ? FACTORY->true_value()
4280 : Factory::false_value()); 4281 : FACTORY->false_value());
4281 Result result = frame_->CallRuntime(Runtime::kNewClosure, 3); 4282 Result result = frame_->CallRuntime(Runtime::kNewClosure, 3);
4282 frame_->Push(&result); 4283 frame_->Push(&result);
4283 } 4284 }
4284 } 4285 }
4285 4286
4286 4287
4287 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { 4288 void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
4288 Comment cmnt(masm_, "[ FunctionLiteral"); 4289 Comment cmnt(masm_, "[ FunctionLiteral");
4289 4290
4290 // Build the function info and instantiate it. 4291 // Build the function info and instantiate it.
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after
4755 if (!boilerplate_.is(rax)) __ movq(boilerplate_, rax); 4756 if (!boilerplate_.is(rax)) __ movq(boilerplate_, rax);
4756 } 4757 }
4757 4758
4758 4759
4759 class DeferredAllocateInNewSpace: public DeferredCode { 4760 class DeferredAllocateInNewSpace: public DeferredCode {
4760 public: 4761 public:
4761 DeferredAllocateInNewSpace(int size, 4762 DeferredAllocateInNewSpace(int size,
4762 Register target, 4763 Register target,
4763 int registers_to_save = 0) 4764 int registers_to_save = 0)
4764 : size_(size), target_(target), registers_to_save_(registers_to_save) { 4765 : size_(size), target_(target), registers_to_save_(registers_to_save) {
4765 ASSERT(size >= kPointerSize && size <= Heap::MaxObjectSizeInNewSpace()); 4766 ASSERT(size >= kPointerSize && size <= HEAP->MaxObjectSizeInNewSpace());
4766 set_comment("[ DeferredAllocateInNewSpace"); 4767 set_comment("[ DeferredAllocateInNewSpace");
4767 } 4768 }
4768 void Generate(); 4769 void Generate();
4769 4770
4770 private: 4771 private:
4771 int size_; 4772 int size_;
4772 Register target_; 4773 Register target_;
4773 int registers_to_save_; 4774 int registers_to_save_;
4774 }; 4775 };
4775 4776
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
4970 4971
4971 // Load the literals array of the function. 4972 // Load the literals array of the function.
4972 __ movq(literals.reg(), 4973 __ movq(literals.reg(),
4973 FieldOperand(literals.reg(), JSFunction::kLiteralsOffset)); 4974 FieldOperand(literals.reg(), JSFunction::kLiteralsOffset));
4974 4975
4975 frame_->Push(&literals); 4976 frame_->Push(&literals);
4976 frame_->Push(Smi::FromInt(node->literal_index())); 4977 frame_->Push(Smi::FromInt(node->literal_index()));
4977 frame_->Push(node->constant_elements()); 4978 frame_->Push(node->constant_elements());
4978 int length = node->values()->length(); 4979 int length = node->values()->length();
4979 Result clone; 4980 Result clone;
4980 if (node->constant_elements()->map() == Heap::fixed_cow_array_map()) { 4981 if (node->constant_elements()->map() == HEAP->fixed_cow_array_map()) {
4981 FastCloneShallowArrayStub stub( 4982 FastCloneShallowArrayStub stub(
4982 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length); 4983 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length);
4983 clone = frame_->CallStub(&stub, 3); 4984 clone = frame_->CallStub(&stub, 3);
4984 __ IncrementCounter(&Counters::cow_arrays_created_stub, 1); 4985 __ IncrementCounter(COUNTERS->cow_arrays_created_stub(), 1);
4985 } else if (node->depth() > 1) { 4986 } else if (node->depth() > 1) {
4986 clone = frame_->CallRuntime(Runtime::kCreateArrayLiteral, 3); 4987 clone = frame_->CallRuntime(Runtime::kCreateArrayLiteral, 3);
4987 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) { 4988 } else if (length > FastCloneShallowArrayStub::kMaximumClonedLength) {
4988 clone = frame_->CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); 4989 clone = frame_->CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
4989 } else { 4990 } else {
4990 FastCloneShallowArrayStub stub( 4991 FastCloneShallowArrayStub stub(
4991 FastCloneShallowArrayStub::CLONE_ELEMENTS, length); 4992 FastCloneShallowArrayStub::CLONE_ELEMENTS, length);
4992 clone = frame_->CallStub(&stub, 3); 4993 clone = frame_->CallStub(&stub, 3);
4993 } 4994 }
4994 frame_->Push(&clone); 4995 frame_->Push(&clone);
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after
5372 5373
5373 // In a call to eval, we first call %ResolvePossiblyDirectEval to 5374 // In a call to eval, we first call %ResolvePossiblyDirectEval to
5374 // resolve the function we need to call and the receiver of the 5375 // resolve the function we need to call and the receiver of the
5375 // call. Then we call the resolved function using the given 5376 // call. Then we call the resolved function using the given
5376 // arguments. 5377 // arguments.
5377 5378
5378 // Prepare the stack for the call to the resolved function. 5379 // Prepare the stack for the call to the resolved function.
5379 Load(function); 5380 Load(function);
5380 5381
5381 // Allocate a frame slot for the receiver. 5382 // Allocate a frame slot for the receiver.
5382 frame_->Push(Factory::undefined_value()); 5383 frame_->Push(FACTORY->undefined_value());
5383 5384
5384 // Load the arguments. 5385 // Load the arguments.
5385 int arg_count = args->length(); 5386 int arg_count = args->length();
5386 for (int i = 0; i < arg_count; i++) { 5387 for (int i = 0; i < arg_count; i++) {
5387 Load(args->at(i)); 5388 Load(args->at(i));
5388 frame_->SpillTop(); 5389 frame_->SpillTop();
5389 } 5390 }
5390 5391
5391 // Result to hold the result of the function resolution and the 5392 // Result to hold the result of the function resolution and the
5392 // final result of the eval call. 5393 // final result of the eval call.
(...skipping 11 matching lines...) Expand all
5404 // ResolvePossiblyDirectEvalNoLookup by pushing the loaded 5405 // ResolvePossiblyDirectEvalNoLookup by pushing the loaded
5405 // function, the first argument to the eval call and the 5406 // function, the first argument to the eval call and the
5406 // receiver. 5407 // receiver.
5407 Result fun = LoadFromGlobalSlotCheckExtensions(var->AsSlot(), 5408 Result fun = LoadFromGlobalSlotCheckExtensions(var->AsSlot(),
5408 NOT_INSIDE_TYPEOF, 5409 NOT_INSIDE_TYPEOF,
5409 &slow); 5410 &slow);
5410 frame_->Push(&fun); 5411 frame_->Push(&fun);
5411 if (arg_count > 0) { 5412 if (arg_count > 0) {
5412 frame_->PushElementAt(arg_count); 5413 frame_->PushElementAt(arg_count);
5413 } else { 5414 } else {
5414 frame_->Push(Factory::undefined_value()); 5415 frame_->Push(FACTORY->undefined_value());
5415 } 5416 }
5416 frame_->PushParameterAt(-1); 5417 frame_->PushParameterAt(-1);
5417 5418
5418 // Push the strict mode flag. 5419 // Push the strict mode flag.
5419 frame_->Push(Smi::FromInt(strict_mode_flag())); 5420 frame_->Push(Smi::FromInt(strict_mode_flag()));
5420 5421
5421 // Resolve the call. 5422 // Resolve the call.
5422 result = 5423 result =
5423 frame_->CallRuntime(Runtime::kResolvePossiblyDirectEvalNoLookup, 4); 5424 frame_->CallRuntime(Runtime::kResolvePossiblyDirectEvalNoLookup, 4);
5424 5425
5425 done.Jump(&result); 5426 done.Jump(&result);
5426 slow.Bind(); 5427 slow.Bind();
5427 } 5428 }
5428 5429
5429 // Prepare the stack for the call to ResolvePossiblyDirectEval by 5430 // Prepare the stack for the call to ResolvePossiblyDirectEval by
5430 // pushing the loaded function, the first argument to the eval 5431 // pushing the loaded function, the first argument to the eval
5431 // call and the receiver. 5432 // call and the receiver.
5432 frame_->PushElementAt(arg_count + 1); 5433 frame_->PushElementAt(arg_count + 1);
5433 if (arg_count > 0) { 5434 if (arg_count > 0) {
5434 frame_->PushElementAt(arg_count); 5435 frame_->PushElementAt(arg_count);
5435 } else { 5436 } else {
5436 frame_->Push(Factory::undefined_value()); 5437 frame_->Push(FACTORY->undefined_value());
5437 } 5438 }
5438 frame_->PushParameterAt(-1); 5439 frame_->PushParameterAt(-1);
5439 5440
5440 // Push the strict mode flag. 5441 // Push the strict mode flag.
5441 frame_->Push(Smi::FromInt(strict_mode_flag())); 5442 frame_->Push(Smi::FromInt(strict_mode_flag()));
5442 5443
5443 // Resolve the call. 5444 // Resolve the call.
5444 result = frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 4); 5445 result = frame_->CallRuntime(Runtime::kResolvePossiblyDirectEval, 4);
5445 5446
5446 // If we generated fast-case code bind the jump-target where fast 5447 // If we generated fast-case code bind the jump-target where fast
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
5715 // 2 (array): Arguments to the format string. 5716 // 2 (array): Arguments to the format string.
5716 ASSERT_EQ(args->length(), 3); 5717 ASSERT_EQ(args->length(), 3);
5717 #ifdef ENABLE_LOGGING_AND_PROFILING 5718 #ifdef ENABLE_LOGGING_AND_PROFILING
5718 if (ShouldGenerateLog(args->at(0))) { 5719 if (ShouldGenerateLog(args->at(0))) {
5719 Load(args->at(1)); 5720 Load(args->at(1));
5720 Load(args->at(2)); 5721 Load(args->at(2));
5721 frame_->CallRuntime(Runtime::kLog, 2); 5722 frame_->CallRuntime(Runtime::kLog, 2);
5722 } 5723 }
5723 #endif 5724 #endif
5724 // Finally, we're expected to leave a value on the top of the stack. 5725 // Finally, we're expected to leave a value on the top of the stack.
5725 frame_->Push(Factory::undefined_value()); 5726 frame_->Push(FACTORY->undefined_value());
5726 } 5727 }
5727 5728
5728 5729
5729 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { 5730 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
5730 ASSERT(args->length() == 1); 5731 ASSERT(args->length() == 1);
5731 Load(args->at(0)); 5732 Load(args->at(0));
5732 Result value = frame_->Pop(); 5733 Result value = frame_->Pop();
5733 value.ToRegister(); 5734 value.ToRegister();
5734 ASSERT(value.is_valid()); 5735 ASSERT(value.is_valid());
5735 Condition non_negative_smi = masm_->CheckNonNegativeSmi(value.reg()); 5736 Condition non_negative_smi = masm_->CheckNonNegativeSmi(value.reg());
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
5978 void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) { 5979 void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) {
5979 // This generates a fast version of: 5980 // This generates a fast version of:
5980 // (typeof(arg) === 'object' || %_ClassOf(arg) == 'RegExp') 5981 // (typeof(arg) === 'object' || %_ClassOf(arg) == 'RegExp')
5981 ASSERT(args->length() == 1); 5982 ASSERT(args->length() == 1);
5982 Load(args->at(0)); 5983 Load(args->at(0));
5983 Result obj = frame_->Pop(); 5984 Result obj = frame_->Pop();
5984 obj.ToRegister(); 5985 obj.ToRegister();
5985 Condition is_smi = masm_->CheckSmi(obj.reg()); 5986 Condition is_smi = masm_->CheckSmi(obj.reg());
5986 destination()->false_target()->Branch(is_smi); 5987 destination()->false_target()->Branch(is_smi);
5987 5988
5988 __ Move(kScratchRegister, Factory::null_value()); 5989 __ Move(kScratchRegister, FACTORY->null_value());
5989 __ cmpq(obj.reg(), kScratchRegister); 5990 __ cmpq(obj.reg(), kScratchRegister);
5990 destination()->true_target()->Branch(equal); 5991 destination()->true_target()->Branch(equal);
5991 5992
5992 __ movq(kScratchRegister, FieldOperand(obj.reg(), HeapObject::kMapOffset)); 5993 __ movq(kScratchRegister, FieldOperand(obj.reg(), HeapObject::kMapOffset));
5993 // Undetectable objects behave like undefined when tested with typeof. 5994 // Undetectable objects behave like undefined when tested with typeof.
5994 __ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset), 5995 __ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset),
5995 Immediate(1 << Map::kIsUndetectable)); 5996 Immediate(1 << Map::kIsUndetectable));
5996 destination()->false_target()->Branch(not_zero); 5997 destination()->false_target()->Branch(not_zero);
5997 __ movzxbq(kScratchRegister, 5998 __ movzxbq(kScratchRegister,
5998 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); 5999 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset));
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
6070 // Calculate location of the first key name. 6071 // Calculate location of the first key name.
6071 __ addq(map_result_, 6072 __ addq(map_result_,
6072 Immediate(FixedArray::kHeaderSize + 6073 Immediate(FixedArray::kHeaderSize +
6073 DescriptorArray::kFirstIndex * kPointerSize)); 6074 DescriptorArray::kFirstIndex * kPointerSize));
6074 // Loop through all the keys in the descriptor array. If one of these is the 6075 // Loop through all the keys in the descriptor array. If one of these is the
6075 // symbol valueOf the result is false. 6076 // symbol valueOf the result is false.
6076 Label entry, loop; 6077 Label entry, loop;
6077 __ jmp(&entry); 6078 __ jmp(&entry);
6078 __ bind(&loop); 6079 __ bind(&loop);
6079 __ movq(scratch2_, FieldOperand(map_result_, 0)); 6080 __ movq(scratch2_, FieldOperand(map_result_, 0));
6080 __ Cmp(scratch2_, Factory::value_of_symbol()); 6081 __ Cmp(scratch2_, FACTORY->value_of_symbol());
6081 __ j(equal, &false_result); 6082 __ j(equal, &false_result);
6082 __ addq(map_result_, Immediate(kPointerSize)); 6083 __ addq(map_result_, Immediate(kPointerSize));
6083 __ bind(&entry); 6084 __ bind(&entry);
6084 __ cmpq(map_result_, scratch1_); 6085 __ cmpq(map_result_, scratch1_);
6085 __ j(not_equal, &loop); 6086 __ j(not_equal, &loop);
6086 6087
6087 // Reload map as register map_result_ was used as temporary above. 6088 // Reload map as register map_result_ was used as temporary above.
6088 __ movq(map_result_, FieldOperand(object_, HeapObject::kMapOffset)); 6089 __ movq(map_result_, FieldOperand(object_, HeapObject::kMapOffset));
6089 6090
6090 // If a valueOf property is not found on the object check that it's 6091 // If a valueOf property is not found on the object check that it's
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
6282 __ movq(obj.reg(), 6283 __ movq(obj.reg(),
6283 FieldOperand(obj.reg(), JSFunction::kSharedFunctionInfoOffset)); 6284 FieldOperand(obj.reg(), JSFunction::kSharedFunctionInfoOffset));
6284 __ movq(obj.reg(), 6285 __ movq(obj.reg(),
6285 FieldOperand(obj.reg(), 6286 FieldOperand(obj.reg(),
6286 SharedFunctionInfo::kInstanceClassNameOffset)); 6287 SharedFunctionInfo::kInstanceClassNameOffset));
6287 frame_->Push(&obj); 6288 frame_->Push(&obj);
6288 leave.Jump(); 6289 leave.Jump();
6289 6290
6290 // Functions have class 'Function'. 6291 // Functions have class 'Function'.
6291 function.Bind(); 6292 function.Bind();
6292 frame_->Push(Factory::function_class_symbol()); 6293 frame_->Push(FACTORY->function_class_symbol());
6293 leave.Jump(); 6294 leave.Jump();
6294 6295
6295 // Objects with a non-function constructor have class 'Object'. 6296 // Objects with a non-function constructor have class 'Object'.
6296 non_function_constructor.Bind(); 6297 non_function_constructor.Bind();
6297 frame_->Push(Factory::Object_symbol()); 6298 frame_->Push(FACTORY->Object_symbol());
6298 leave.Jump(); 6299 leave.Jump();
6299 6300
6300 // Non-JS objects have class null. 6301 // Non-JS objects have class null.
6301 null.Bind(); 6302 null.Bind();
6302 frame_->Push(Factory::null_value()); 6303 frame_->Push(FACTORY->null_value());
6303 6304
6304 // All done. 6305 // All done.
6305 leave.Bind(); 6306 leave.Bind();
6306 } 6307 }
6307 6308
6308 6309
6309 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { 6310 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
6310 ASSERT(args->length() == 1); 6311 ASSERT(args->length() == 1);
6311 JumpTarget leave; 6312 JumpTarget leave;
6312 Load(args->at(0)); // Load the object. 6313 Load(args->at(0)); // Load the object.
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after
6661 } 6662 }
6662 6663
6663 6664
6664 void CodeGenerator::GenerateGetFromCache(ZoneList<Expression*>* args) { 6665 void CodeGenerator::GenerateGetFromCache(ZoneList<Expression*>* args) {
6665 ASSERT_EQ(2, args->length()); 6666 ASSERT_EQ(2, args->length());
6666 6667
6667 ASSERT_NE(NULL, args->at(0)->AsLiteral()); 6668 ASSERT_NE(NULL, args->at(0)->AsLiteral());
6668 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value(); 6669 int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->handle()))->value();
6669 6670
6670 Handle<FixedArray> jsfunction_result_caches( 6671 Handle<FixedArray> jsfunction_result_caches(
6671 Top::global_context()->jsfunction_result_caches()); 6672 Isolate::Current()->global_context()->jsfunction_result_caches());
6672 if (jsfunction_result_caches->length() <= cache_id) { 6673 if (jsfunction_result_caches->length() <= cache_id) {
6673 __ Abort("Attempt to use undefined cache."); 6674 __ Abort("Attempt to use undefined cache.");
6674 frame_->Push(Factory::undefined_value()); 6675 frame_->Push(FACTORY->undefined_value());
6675 return; 6676 return;
6676 } 6677 }
6677 6678
6678 Load(args->at(1)); 6679 Load(args->at(1));
6679 Result key = frame_->Pop(); 6680 Result key = frame_->Pop();
6680 key.ToRegister(); 6681 key.ToRegister();
6681 6682
6682 Result cache = allocator()->Allocate(); 6683 Result cache = allocator()->Allocate();
6683 ASSERT(cache.is_valid()); 6684 ASSERT(cache.is_valid());
6684 __ movq(cache.reg(), ContextOperand(rsi, Context::GLOBAL_INDEX)); 6685 __ movq(cache.reg(), ContextOperand(rsi, Context::GLOBAL_INDEX));
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
6830 __ InNewSpace(tmp1.reg(), tmp2.reg(), equal, &done); 6831 __ InNewSpace(tmp1.reg(), tmp2.reg(), equal, &done);
6831 // Possible optimization: do a check that both values are smis 6832 // Possible optimization: do a check that both values are smis
6832 // (or them and test against Smi mask.) 6833 // (or them and test against Smi mask.)
6833 6834
6834 __ movq(tmp2.reg(), tmp1.reg()); 6835 __ movq(tmp2.reg(), tmp1.reg());
6835 __ RecordWriteHelper(tmp1.reg(), index1.reg(), object.reg()); 6836 __ RecordWriteHelper(tmp1.reg(), index1.reg(), object.reg());
6836 __ RecordWriteHelper(tmp2.reg(), index2.reg(), object.reg()); 6837 __ RecordWriteHelper(tmp2.reg(), index2.reg(), object.reg());
6837 __ bind(&done); 6838 __ bind(&done);
6838 6839
6839 deferred->BindExit(); 6840 deferred->BindExit();
6840 frame_->Push(Factory::undefined_value()); 6841 frame_->Push(FACTORY->undefined_value());
6841 } 6842 }
6842 6843
6843 6844
6844 void CodeGenerator::GenerateCallFunction(ZoneList<Expression*>* args) { 6845 void CodeGenerator::GenerateCallFunction(ZoneList<Expression*>* args) {
6845 Comment cmnt(masm_, "[ GenerateCallFunction"); 6846 Comment cmnt(masm_, "[ GenerateCallFunction");
6846 6847
6847 ASSERT(args->length() >= 2); 6848 ASSERT(args->length() >= 2);
6848 6849
6849 int n_args = args->length() - 2; // for receiver and function. 6850 int n_args = args->length() - 2; // for receiver and function.
6850 Load(args->at(0)); // receiver 6851 Load(args->at(0)); // receiver
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
7174 Result number = allocator()->Allocate(); 7175 Result number = allocator()->Allocate();
7175 ASSERT(number.is_valid()); 7176 ASSERT(number.is_valid());
7176 __ movl(number.reg(), FieldOperand(string.reg(), String::kHashFieldOffset)); 7177 __ movl(number.reg(), FieldOperand(string.reg(), String::kHashFieldOffset));
7177 __ IndexFromHash(number.reg(), number.reg()); 7178 __ IndexFromHash(number.reg(), number.reg());
7178 string.Unuse(); 7179 string.Unuse();
7179 frame_->Push(&number); 7180 frame_->Push(&number);
7180 } 7181 }
7181 7182
7182 7183
7183 void CodeGenerator::GenerateFastAsciiArrayJoin(ZoneList<Expression*>* args) { 7184 void CodeGenerator::GenerateFastAsciiArrayJoin(ZoneList<Expression*>* args) {
7184 frame_->Push(Factory::undefined_value()); 7185 frame_->Push(FACTORY->undefined_value());
7185 } 7186 }
7186 7187
7187 7188
7188 void CodeGenerator::VisitCallRuntime(CallRuntime* node) { 7189 void CodeGenerator::VisitCallRuntime(CallRuntime* node) {
7189 if (CheckForInlineRuntimeCall(node)) { 7190 if (CheckForInlineRuntimeCall(node)) {
7190 return; 7191 return;
7191 } 7192 }
7192 7193
7193 ZoneList<Expression*>* args = node->arguments(); 7194 ZoneList<Expression*>* args = node->arguments();
7194 Comment cmnt(masm_, "[ CallRuntime"); 7195 Comment cmnt(masm_, "[ CallRuntime");
7195 Runtime::Function* function = node->function(); 7196 const Runtime::Function* function = node->function();
7196 7197
7197 if (function == NULL) { 7198 if (function == NULL) {
7198 // Push the builtins object found in the current global object. 7199 // Push the builtins object found in the current global object.
7199 Result temp = allocator()->Allocate(); 7200 Result temp = allocator()->Allocate();
7200 ASSERT(temp.is_valid()); 7201 ASSERT(temp.is_valid());
7201 __ movq(temp.reg(), GlobalObjectOperand()); 7202 __ movq(temp.reg(), GlobalObjectOperand());
7202 __ movq(temp.reg(), 7203 __ movq(temp.reg(),
7203 FieldOperand(temp.reg(), GlobalObject::kBuiltinsOffset)); 7204 FieldOperand(temp.reg(), GlobalObject::kBuiltinsOffset));
7204 frame_->Push(&temp); 7205 frame_->Push(&temp);
7205 } 7206 }
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
7269 // variable. Sync the virtual frame eagerly so we can push the 7270 // variable. Sync the virtual frame eagerly so we can push the
7270 // arguments directly into place. 7271 // arguments directly into place.
7271 frame_->SyncRange(0, frame_->element_count() - 1); 7272 frame_->SyncRange(0, frame_->element_count() - 1);
7272 frame_->EmitPush(rsi); 7273 frame_->EmitPush(rsi);
7273 frame_->EmitPush(variable->name()); 7274 frame_->EmitPush(variable->name());
7274 Result answer = frame_->CallRuntime(Runtime::kDeleteContextSlot, 2); 7275 Result answer = frame_->CallRuntime(Runtime::kDeleteContextSlot, 2);
7275 frame_->Push(&answer); 7276 frame_->Push(&answer);
7276 } else { 7277 } else {
7277 // Default: Result of deleting non-global, not dynamically 7278 // Default: Result of deleting non-global, not dynamically
7278 // introduced variables is false. 7279 // introduced variables is false.
7279 frame_->Push(Factory::false_value()); 7280 frame_->Push(FACTORY->false_value());
7280 } 7281 }
7281 } else { 7282 } else {
7282 // Default: Result of deleting expressions is true. 7283 // Default: Result of deleting expressions is true.
7283 Load(node->expression()); // may have side-effects 7284 Load(node->expression()); // may have side-effects
7284 frame_->SetElementAt(0, Factory::true_value()); 7285 frame_->SetElementAt(0, FACTORY->true_value());
7285 } 7286 }
7286 7287
7287 } else if (op == Token::TYPEOF) { 7288 } else if (op == Token::TYPEOF) {
7288 // Special case for loading the typeof expression; see comment on 7289 // Special case for loading the typeof expression; see comment on
7289 // LoadTypeofExpression(). 7290 // LoadTypeofExpression().
7290 LoadTypeofExpression(node->expression()); 7291 LoadTypeofExpression(node->expression());
7291 Result answer = frame_->CallRuntime(Runtime::kTypeof, 1); 7292 Result answer = frame_->CallRuntime(Runtime::kTypeof, 1);
7292 frame_->Push(&answer); 7293 frame_->Push(&answer);
7293 7294
7294 } else if (op == Token::VOID) { 7295 } else if (op == Token::VOID) {
7295 Expression* expression = node->expression(); 7296 Expression* expression = node->expression();
7296 if (expression && expression->AsLiteral() && ( 7297 if (expression && expression->AsLiteral() && (
7297 expression->AsLiteral()->IsTrue() || 7298 expression->AsLiteral()->IsTrue() ||
7298 expression->AsLiteral()->IsFalse() || 7299 expression->AsLiteral()->IsFalse() ||
7299 expression->AsLiteral()->handle()->IsNumber() || 7300 expression->AsLiteral()->handle()->IsNumber() ||
7300 expression->AsLiteral()->handle()->IsString() || 7301 expression->AsLiteral()->handle()->IsString() ||
7301 expression->AsLiteral()->handle()->IsJSRegExp() || 7302 expression->AsLiteral()->handle()->IsJSRegExp() ||
7302 expression->AsLiteral()->IsNull())) { 7303 expression->AsLiteral()->IsNull())) {
7303 // Omit evaluating the value of the primitive literal. 7304 // Omit evaluating the value of the primitive literal.
7304 // It will be discarded anyway, and can have no side effect. 7305 // It will be discarded anyway, and can have no side effect.
7305 frame_->Push(Factory::undefined_value()); 7306 frame_->Push(FACTORY->undefined_value());
7306 } else { 7307 } else {
7307 Load(node->expression()); 7308 Load(node->expression());
7308 frame_->SetElementAt(0, Factory::undefined_value()); 7309 frame_->SetElementAt(0, FACTORY->undefined_value());
7309 } 7310 }
7310 7311
7311 } else { 7312 } else {
7312 bool can_overwrite = node->expression()->ResultOverwriteAllowed(); 7313 bool can_overwrite = node->expression()->ResultOverwriteAllowed();
7313 UnaryOverwriteMode overwrite = 7314 UnaryOverwriteMode overwrite =
7314 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE; 7315 can_overwrite ? UNARY_OVERWRITE : UNARY_NO_OVERWRITE;
7315 bool no_negative_zero = node->expression()->no_negative_zero(); 7316 bool no_negative_zero = node->expression()->no_negative_zero();
7316 Load(node->expression()); 7317 Load(node->expression());
7317 switch (op) { 7318 switch (op) {
7318 case Token::NOT: 7319 case Token::NOT:
(...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after
7770 (operation != NULL && operation->op() == Token::TYPEOF) && 7771 (operation != NULL && operation->op() == Token::TYPEOF) &&
7771 (right->AsLiteral() != NULL && 7772 (right->AsLiteral() != NULL &&
7772 right->AsLiteral()->handle()->IsString())) { 7773 right->AsLiteral()->handle()->IsString())) {
7773 Handle<String> check(Handle<String>::cast(right->AsLiteral()->handle())); 7774 Handle<String> check(Handle<String>::cast(right->AsLiteral()->handle()));
7774 7775
7775 // Load the operand and move it to a register. 7776 // Load the operand and move it to a register.
7776 LoadTypeofExpression(operation->expression()); 7777 LoadTypeofExpression(operation->expression());
7777 Result answer = frame_->Pop(); 7778 Result answer = frame_->Pop();
7778 answer.ToRegister(); 7779 answer.ToRegister();
7779 7780
7780 if (check->Equals(Heap::number_symbol())) { 7781 if (check->Equals(HEAP->number_symbol())) {
7781 Condition is_smi = masm_->CheckSmi(answer.reg()); 7782 Condition is_smi = masm_->CheckSmi(answer.reg());
7782 destination()->true_target()->Branch(is_smi); 7783 destination()->true_target()->Branch(is_smi);
7783 frame_->Spill(answer.reg()); 7784 frame_->Spill(answer.reg());
7784 __ movq(answer.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset)); 7785 __ movq(answer.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset));
7785 __ CompareRoot(answer.reg(), Heap::kHeapNumberMapRootIndex); 7786 __ CompareRoot(answer.reg(), Heap::kHeapNumberMapRootIndex);
7786 answer.Unuse(); 7787 answer.Unuse();
7787 destination()->Split(equal); 7788 destination()->Split(equal);
7788 7789
7789 } else if (check->Equals(Heap::string_symbol())) { 7790 } else if (check->Equals(HEAP->string_symbol())) {
7790 Condition is_smi = masm_->CheckSmi(answer.reg()); 7791 Condition is_smi = masm_->CheckSmi(answer.reg());
7791 destination()->false_target()->Branch(is_smi); 7792 destination()->false_target()->Branch(is_smi);
7792 7793
7793 // It can be an undetectable string object. 7794 // It can be an undetectable string object.
7794 __ movq(kScratchRegister, 7795 __ movq(kScratchRegister,
7795 FieldOperand(answer.reg(), HeapObject::kMapOffset)); 7796 FieldOperand(answer.reg(), HeapObject::kMapOffset));
7796 __ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset), 7797 __ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset),
7797 Immediate(1 << Map::kIsUndetectable)); 7798 Immediate(1 << Map::kIsUndetectable));
7798 destination()->false_target()->Branch(not_zero); 7799 destination()->false_target()->Branch(not_zero);
7799 __ CmpInstanceType(kScratchRegister, FIRST_NONSTRING_TYPE); 7800 __ CmpInstanceType(kScratchRegister, FIRST_NONSTRING_TYPE);
7800 answer.Unuse(); 7801 answer.Unuse();
7801 destination()->Split(below); // Unsigned byte comparison needed. 7802 destination()->Split(below); // Unsigned byte comparison needed.
7802 7803
7803 } else if (check->Equals(Heap::boolean_symbol())) { 7804 } else if (check->Equals(HEAP->boolean_symbol())) {
7804 __ CompareRoot(answer.reg(), Heap::kTrueValueRootIndex); 7805 __ CompareRoot(answer.reg(), Heap::kTrueValueRootIndex);
7805 destination()->true_target()->Branch(equal); 7806 destination()->true_target()->Branch(equal);
7806 __ CompareRoot(answer.reg(), Heap::kFalseValueRootIndex); 7807 __ CompareRoot(answer.reg(), Heap::kFalseValueRootIndex);
7807 answer.Unuse(); 7808 answer.Unuse();
7808 destination()->Split(equal); 7809 destination()->Split(equal);
7809 7810
7810 } else if (check->Equals(Heap::undefined_symbol())) { 7811 } else if (check->Equals(HEAP->undefined_symbol())) {
7811 __ CompareRoot(answer.reg(), Heap::kUndefinedValueRootIndex); 7812 __ CompareRoot(answer.reg(), Heap::kUndefinedValueRootIndex);
7812 destination()->true_target()->Branch(equal); 7813 destination()->true_target()->Branch(equal);
7813 7814
7814 Condition is_smi = masm_->CheckSmi(answer.reg()); 7815 Condition is_smi = masm_->CheckSmi(answer.reg());
7815 destination()->false_target()->Branch(is_smi); 7816 destination()->false_target()->Branch(is_smi);
7816 7817
7817 // It can be an undetectable object. 7818 // It can be an undetectable object.
7818 __ movq(kScratchRegister, 7819 __ movq(kScratchRegister,
7819 FieldOperand(answer.reg(), HeapObject::kMapOffset)); 7820 FieldOperand(answer.reg(), HeapObject::kMapOffset));
7820 __ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset), 7821 __ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset),
7821 Immediate(1 << Map::kIsUndetectable)); 7822 Immediate(1 << Map::kIsUndetectable));
7822 answer.Unuse(); 7823 answer.Unuse();
7823 destination()->Split(not_zero); 7824 destination()->Split(not_zero);
7824 7825
7825 } else if (check->Equals(Heap::function_symbol())) { 7826 } else if (check->Equals(HEAP->function_symbol())) {
7826 Condition is_smi = masm_->CheckSmi(answer.reg()); 7827 Condition is_smi = masm_->CheckSmi(answer.reg());
7827 destination()->false_target()->Branch(is_smi); 7828 destination()->false_target()->Branch(is_smi);
7828 frame_->Spill(answer.reg()); 7829 frame_->Spill(answer.reg());
7829 __ CmpObjectType(answer.reg(), JS_FUNCTION_TYPE, answer.reg()); 7830 __ CmpObjectType(answer.reg(), JS_FUNCTION_TYPE, answer.reg());
7830 destination()->true_target()->Branch(equal); 7831 destination()->true_target()->Branch(equal);
7831 // Regular expressions are callable so typeof == 'function'. 7832 // Regular expressions are callable so typeof == 'function'.
7832 __ CmpInstanceType(answer.reg(), JS_REGEXP_TYPE); 7833 __ CmpInstanceType(answer.reg(), JS_REGEXP_TYPE);
7833 answer.Unuse(); 7834 answer.Unuse();
7834 destination()->Split(equal); 7835 destination()->Split(equal);
7835 7836
7836 } else if (check->Equals(Heap::object_symbol())) { 7837 } else if (check->Equals(HEAP->object_symbol())) {
7837 Condition is_smi = masm_->CheckSmi(answer.reg()); 7838 Condition is_smi = masm_->CheckSmi(answer.reg());
7838 destination()->false_target()->Branch(is_smi); 7839 destination()->false_target()->Branch(is_smi);
7839 __ CompareRoot(answer.reg(), Heap::kNullValueRootIndex); 7840 __ CompareRoot(answer.reg(), Heap::kNullValueRootIndex);
7840 destination()->true_target()->Branch(equal); 7841 destination()->true_target()->Branch(equal);
7841 7842
7842 // Regular expressions are typeof == 'function', not 'object'. 7843 // Regular expressions are typeof == 'function', not 'object'.
7843 __ CmpObjectType(answer.reg(), JS_REGEXP_TYPE, kScratchRegister); 7844 __ CmpObjectType(answer.reg(), JS_REGEXP_TYPE, kScratchRegister);
7844 destination()->false_target()->Branch(equal); 7845 destination()->false_target()->Branch(equal);
7845 7846
7846 // It can be an undetectable object. 7847 // It can be an undetectable object.
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
7990 Register receiver_; 7991 Register receiver_;
7991 Handle<String> name_; 7992 Handle<String> name_;
7992 }; 7993 };
7993 7994
7994 7995
7995 void DeferredReferenceGetNamedValue::Generate() { 7996 void DeferredReferenceGetNamedValue::Generate() {
7996 if (!receiver_.is(rax)) { 7997 if (!receiver_.is(rax)) {
7997 __ movq(rax, receiver_); 7998 __ movq(rax, receiver_);
7998 } 7999 }
7999 __ Move(rcx, name_); 8000 __ Move(rcx, name_);
8000 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 8001 Handle<Code> ic(Isolate::Current()->builtins()->builtin(
8002 Builtins::LoadIC_Initialize));
8001 __ Call(ic, RelocInfo::CODE_TARGET); 8003 __ Call(ic, RelocInfo::CODE_TARGET);
8002 // The call must be followed by a test rax instruction to indicate 8004 // The call must be followed by a test rax instruction to indicate
8003 // that the inobject property case was inlined. 8005 // that the inobject property case was inlined.
8004 // 8006 //
8005 // Store the delta to the map check instruction here in the test 8007 // Store the delta to the map check instruction here in the test
8006 // instruction. Use masm_-> instead of the __ macro since the 8008 // instruction. Use masm_-> instead of the __ macro since the
8007 // latter can't return a value. 8009 // latter can't return a value.
8008 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); 8010 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site());
8009 // Here we use masm_-> instead of the __ macro because this is the 8011 // Here we use masm_-> instead of the __ macro because this is the
8010 // instruction that gets patched and coverage code gets in the way. 8012 // instruction that gets patched and coverage code gets in the way.
8011 masm_->testl(rax, Immediate(-delta_to_patch_site)); 8013 masm_->testl(rax, Immediate(-delta_to_patch_site));
8012 __ IncrementCounter(&Counters::named_load_inline_miss, 1); 8014 __ IncrementCounter(COUNTERS->named_load_inline_miss(), 1);
8013 8015
8014 if (!dst_.is(rax)) __ movq(dst_, rax); 8016 if (!dst_.is(rax)) __ movq(dst_, rax);
8015 } 8017 }
8016 8018
8017 8019
8018 class DeferredReferenceGetKeyedValue: public DeferredCode { 8020 class DeferredReferenceGetKeyedValue: public DeferredCode {
8019 public: 8021 public:
8020 explicit DeferredReferenceGetKeyedValue(Register dst, 8022 explicit DeferredReferenceGetKeyedValue(Register dst,
8021 Register receiver, 8023 Register receiver,
8022 Register key) 8024 Register key)
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
8055 } else { 8057 } else {
8056 __ movq(rax, key_); 8058 __ movq(rax, key_);
8057 __ movq(rdx, receiver_); 8059 __ movq(rdx, receiver_);
8058 } 8060 }
8059 // Calculate the delta from the IC call instruction to the map check 8061 // Calculate the delta from the IC call instruction to the map check
8060 // movq instruction in the inlined version. This delta is stored in 8062 // movq instruction in the inlined version. This delta is stored in
8061 // a test(rax, delta) instruction after the call so that we can find 8063 // a test(rax, delta) instruction after the call so that we can find
8062 // it in the IC initialization code and patch the movq instruction. 8064 // it in the IC initialization code and patch the movq instruction.
8063 // This means that we cannot allow test instructions after calls to 8065 // This means that we cannot allow test instructions after calls to
8064 // KeyedLoadIC stubs in other places. 8066 // KeyedLoadIC stubs in other places.
8065 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 8067 Handle<Code> ic(Isolate::Current()->builtins()->builtin(
8068 Builtins::KeyedLoadIC_Initialize));
8066 __ Call(ic, RelocInfo::CODE_TARGET); 8069 __ Call(ic, RelocInfo::CODE_TARGET);
8067 // The delta from the start of the map-compare instruction to the 8070 // The delta from the start of the map-compare instruction to the
8068 // test instruction. We use masm_-> directly here instead of the __ 8071 // test instruction. We use masm_-> directly here instead of the __
8069 // macro because the macro sometimes uses macro expansion to turn 8072 // macro because the macro sometimes uses macro expansion to turn
8070 // into something that can't return a value. This is encountered 8073 // into something that can't return a value. This is encountered
8071 // when doing generated code coverage tests. 8074 // when doing generated code coverage tests.
8072 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); 8075 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site());
8073 // Here we use masm_-> instead of the __ macro because this is the 8076 // Here we use masm_-> instead of the __ macro because this is the
8074 // instruction that gets patched and coverage code gets in the way. 8077 // instruction that gets patched and coverage code gets in the way.
8075 // TODO(X64): Consider whether it's worth switching the test to a 8078 // TODO(X64): Consider whether it's worth switching the test to a
8076 // 7-byte NOP with non-zero immediate (0f 1f 80 xxxxxxxx) which won't 8079 // 7-byte NOP with non-zero immediate (0f 1f 80 xxxxxxxx) which won't
8077 // be generated normally. 8080 // be generated normally.
8078 masm_->testl(rax, Immediate(-delta_to_patch_site)); 8081 masm_->testl(rax, Immediate(-delta_to_patch_site));
8079 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1); 8082 __ IncrementCounter(COUNTERS->keyed_load_inline_miss(), 1);
8080 8083
8081 if (!dst_.is(rax)) __ movq(dst_, rax); 8084 if (!dst_.is(rax)) __ movq(dst_, rax);
8082 } 8085 }
8083 8086
8084 8087
8085 class DeferredReferenceSetKeyedValue: public DeferredCode { 8088 class DeferredReferenceSetKeyedValue: public DeferredCode {
8086 public: 8089 public:
8087 DeferredReferenceSetKeyedValue(Register value, 8090 DeferredReferenceSetKeyedValue(Register value,
8088 Register key, 8091 Register key,
8089 Register receiver, 8092 Register receiver,
(...skipping 12 matching lines...) Expand all
8102 private: 8105 private:
8103 Register value_; 8106 Register value_;
8104 Register key_; 8107 Register key_;
8105 Register receiver_; 8108 Register receiver_;
8106 Label patch_site_; 8109 Label patch_site_;
8107 StrictModeFlag strict_mode_; 8110 StrictModeFlag strict_mode_;
8108 }; 8111 };
8109 8112
8110 8113
8111 void DeferredReferenceSetKeyedValue::Generate() { 8114 void DeferredReferenceSetKeyedValue::Generate() {
8112 __ IncrementCounter(&Counters::keyed_store_inline_miss, 1); 8115 __ IncrementCounter(COUNTERS->keyed_store_inline_miss(), 1);
8113 // Move value, receiver, and key to registers rax, rdx, and rcx, as 8116 // Move value, receiver, and key to registers rax, rdx, and rcx, as
8114 // the IC stub expects. 8117 // the IC stub expects.
8115 // Move value to rax, using xchg if the receiver or key is in rax. 8118 // Move value to rax, using xchg if the receiver or key is in rax.
8116 if (!value_.is(rax)) { 8119 if (!value_.is(rax)) {
8117 if (!receiver_.is(rax) && !key_.is(rax)) { 8120 if (!receiver_.is(rax) && !key_.is(rax)) {
8118 __ movq(rax, value_); 8121 __ movq(rax, value_);
8119 } else { 8122 } else {
8120 __ xchg(rax, value_); 8123 __ xchg(rax, value_);
8121 // Update receiver_ and key_ if they are affected by the swap. 8124 // Update receiver_ and key_ if they are affected by the swap.
8122 if (receiver_.is(rax)) { 8125 if (receiver_.is(rax)) {
(...skipping 26 matching lines...) Expand all
8149 __ movq(rcx, key_); 8152 __ movq(rcx, key_);
8150 } 8153 }
8151 } else if (key_.is(rcx)) { 8154 } else if (key_.is(rcx)) {
8152 __ movq(rdx, receiver_); 8155 __ movq(rdx, receiver_);
8153 } else { 8156 } else {
8154 __ movq(rcx, key_); 8157 __ movq(rcx, key_);
8155 __ movq(rdx, receiver_); 8158 __ movq(rdx, receiver_);
8156 } 8159 }
8157 8160
8158 // Call the IC stub. 8161 // Call the IC stub.
8159 Handle<Code> ic(Builtins::builtin( 8162 Handle<Code> ic(Isolate::Current()->builtins()->builtin(
8160 (strict_mode_ == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict 8163 (strict_mode_ == kStrictMode) ? Builtins::KeyedStoreIC_Initialize_Strict
8161 : Builtins::KeyedStoreIC_Initialize)); 8164 : Builtins::KeyedStoreIC_Initialize));
8162 __ Call(ic, RelocInfo::CODE_TARGET); 8165 __ Call(ic, RelocInfo::CODE_TARGET);
8163 // The delta from the start of the map-compare instructions (initial movq) 8166 // The delta from the start of the map-compare instructions (initial movq)
8164 // to the test instruction. We use masm_-> directly here instead of the 8167 // to the test instruction. We use masm_-> directly here instead of the
8165 // __ macro because the macro sometimes uses macro expansion to turn 8168 // __ macro because the macro sometimes uses macro expansion to turn
8166 // into something that can't return a value. This is encountered 8169 // into something that can't return a value. This is encountered
8167 // when doing generated code coverage tests. 8170 // when doing generated code coverage tests.
8168 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); 8171 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site());
8169 // Here we use masm_-> instead of the __ macro because this is the 8172 // Here we use masm_-> instead of the __ macro because this is the
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
8218 DeferredReferenceGetNamedValue* deferred = 8221 DeferredReferenceGetNamedValue* deferred =
8219 new DeferredReferenceGetNamedValue(result.reg(), receiver.reg(), name); 8222 new DeferredReferenceGetNamedValue(result.reg(), receiver.reg(), name);
8220 8223
8221 // Check that the receiver is a heap object. 8224 // Check that the receiver is a heap object.
8222 __ JumpIfSmi(receiver.reg(), deferred->entry_label()); 8225 __ JumpIfSmi(receiver.reg(), deferred->entry_label());
8223 8226
8224 __ bind(deferred->patch_site()); 8227 __ bind(deferred->patch_site());
8225 // This is the map check instruction that will be patched (so we can't 8228 // This is the map check instruction that will be patched (so we can't
8226 // use the double underscore macro that may insert instructions). 8229 // use the double underscore macro that may insert instructions).
8227 // Initially use an invalid map to force a failure. 8230 // Initially use an invalid map to force a failure.
8228 masm()->movq(kScratchRegister, Factory::null_value(), 8231 masm()->movq(kScratchRegister, FACTORY->null_value(),
8229 RelocInfo::EMBEDDED_OBJECT); 8232 RelocInfo::EMBEDDED_OBJECT);
8230 masm()->cmpq(FieldOperand(receiver.reg(), HeapObject::kMapOffset), 8233 masm()->cmpq(FieldOperand(receiver.reg(), HeapObject::kMapOffset),
8231 kScratchRegister); 8234 kScratchRegister);
8232 // This branch is always a forwards branch so it's always a fixed 8235 // This branch is always a forwards branch so it's always a fixed
8233 // size which allows the assert below to succeed and patching to work. 8236 // size which allows the assert below to succeed and patching to work.
8234 // Don't use deferred->Branch(...), since that might add coverage code. 8237 // Don't use deferred->Branch(...), since that might add coverage code.
8235 masm()->j(not_equal, deferred->entry_label()); 8238 masm()->j(not_equal, deferred->entry_label());
8236 8239
8237 // The delta from the patch label to the load offset must be 8240 // The delta from the patch label to the load offset must be
8238 // statically known. 8241 // statically known.
8239 ASSERT(masm()->SizeOfCodeGeneratedSince(deferred->patch_site()) == 8242 ASSERT(masm()->SizeOfCodeGeneratedSince(deferred->patch_site()) ==
8240 LoadIC::kOffsetToLoadInstruction); 8243 LoadIC::kOffsetToLoadInstruction);
8241 // The initial (invalid) offset has to be large enough to force 8244 // The initial (invalid) offset has to be large enough to force
8242 // a 32-bit instruction encoding to allow patching with an 8245 // a 32-bit instruction encoding to allow patching with an
8243 // arbitrary offset. Use kMaxInt (minus kHeapObjectTag). 8246 // arbitrary offset. Use kMaxInt (minus kHeapObjectTag).
8244 int offset = kMaxInt; 8247 int offset = kMaxInt;
8245 masm()->movq(result.reg(), FieldOperand(receiver.reg(), offset)); 8248 masm()->movq(result.reg(), FieldOperand(receiver.reg(), offset));
8246 8249
8247 __ IncrementCounter(&Counters::named_load_inline, 1); 8250 __ IncrementCounter(COUNTERS->named_load_inline(), 1);
8248 deferred->BindExit(); 8251 deferred->BindExit();
8249 } 8252 }
8250 ASSERT(frame()->height() == original_height - 1); 8253 ASSERT(frame()->height() == original_height - 1);
8251 return result; 8254 return result;
8252 } 8255 }
8253 8256
8254 8257
8255 Result CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) { 8258 Result CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) {
8256 #ifdef DEBUG 8259 #ifdef DEBUG
8257 int expected_height = frame()->height() - (is_contextual ? 1 : 2); 8260 int expected_height = frame()->height() - (is_contextual ? 1 : 2);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
8295 Condition is_smi = masm()->CheckSmi(receiver.reg()); 8298 Condition is_smi = masm()->CheckSmi(receiver.reg());
8296 slow.Branch(is_smi, &value, &receiver); 8299 slow.Branch(is_smi, &value, &receiver);
8297 8300
8298 // This is the map check instruction that will be patched. 8301 // This is the map check instruction that will be patched.
8299 // Initially use an invalid map to force a failure. The exact 8302 // Initially use an invalid map to force a failure. The exact
8300 // instruction sequence is important because we use the 8303 // instruction sequence is important because we use the
8301 // kOffsetToStoreInstruction constant for patching. We avoid using 8304 // kOffsetToStoreInstruction constant for patching. We avoid using
8302 // the __ macro for the following two instructions because it 8305 // the __ macro for the following two instructions because it
8303 // might introduce extra instructions. 8306 // might introduce extra instructions.
8304 __ bind(&patch_site); 8307 __ bind(&patch_site);
8305 masm()->movq(kScratchRegister, Factory::null_value(), 8308 masm()->movq(kScratchRegister, FACTORY->null_value(),
8306 RelocInfo::EMBEDDED_OBJECT); 8309 RelocInfo::EMBEDDED_OBJECT);
8307 masm()->cmpq(FieldOperand(receiver.reg(), HeapObject::kMapOffset), 8310 masm()->cmpq(FieldOperand(receiver.reg(), HeapObject::kMapOffset),
8308 kScratchRegister); 8311 kScratchRegister);
8309 // This branch is always a forwards branch so it's always a fixed size 8312 // This branch is always a forwards branch so it's always a fixed size
8310 // which allows the assert below to succeed and patching to work. 8313 // which allows the assert below to succeed and patching to work.
8311 slow.Branch(not_equal, &value, &receiver); 8314 slow.Branch(not_equal, &value, &receiver);
8312 8315
8313 // The delta from the patch label to the store offset must be 8316 // The delta from the patch label to the store offset must be
8314 // statically known. 8317 // statically known.
8315 ASSERT(masm()->SizeOfCodeGeneratedSince(&patch_site) == 8318 ASSERT(masm()->SizeOfCodeGeneratedSince(&patch_site) ==
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
8409 __ JumpIfSmi(receiver.reg(), deferred->entry_label()); 8412 __ JumpIfSmi(receiver.reg(), deferred->entry_label());
8410 8413
8411 // Check that the receiver has the expected map. 8414 // Check that the receiver has the expected map.
8412 // Initially, use an invalid map. The map is patched in the IC 8415 // Initially, use an invalid map. The map is patched in the IC
8413 // initialization code. 8416 // initialization code.
8414 __ bind(deferred->patch_site()); 8417 __ bind(deferred->patch_site());
8415 // Use masm-> here instead of the double underscore macro since extra 8418 // Use masm-> here instead of the double underscore macro since extra
8416 // coverage code can interfere with the patching. Do not use a load 8419 // coverage code can interfere with the patching. Do not use a load
8417 // from the root array to load null_value, since the load must be patched 8420 // from the root array to load null_value, since the load must be patched
8418 // with the expected receiver map, which is not in the root array. 8421 // with the expected receiver map, which is not in the root array.
8419 masm_->movq(kScratchRegister, Factory::null_value(), 8422 masm_->movq(kScratchRegister, FACTORY->null_value(),
8420 RelocInfo::EMBEDDED_OBJECT); 8423 RelocInfo::EMBEDDED_OBJECT);
8421 masm_->cmpq(FieldOperand(receiver.reg(), HeapObject::kMapOffset), 8424 masm_->cmpq(FieldOperand(receiver.reg(), HeapObject::kMapOffset),
8422 kScratchRegister); 8425 kScratchRegister);
8423 deferred->Branch(not_equal); 8426 deferred->Branch(not_equal);
8424 8427
8425 __ JumpUnlessNonNegativeSmi(key.reg(), deferred->entry_label()); 8428 __ JumpUnlessNonNegativeSmi(key.reg(), deferred->entry_label());
8426 8429
8427 // Get the elements array from the receiver. 8430 // Get the elements array from the receiver.
8428 __ movq(elements.reg(), 8431 __ movq(elements.reg(),
8429 FieldOperand(receiver.reg(), JSObject::kElementsOffset)); 8432 FieldOperand(receiver.reg(), JSObject::kElementsOffset));
(...skipping 14 matching lines...) Expand all
8444 SmiIndex index = 8447 SmiIndex index =
8445 masm_->SmiToIndex(kScratchRegister, key.reg(), kPointerSizeLog2); 8448 masm_->SmiToIndex(kScratchRegister, key.reg(), kPointerSizeLog2);
8446 __ movq(elements.reg(), 8449 __ movq(elements.reg(),
8447 FieldOperand(elements.reg(), 8450 FieldOperand(elements.reg(),
8448 index.reg, 8451 index.reg,
8449 index.scale, 8452 index.scale,
8450 FixedArray::kHeaderSize)); 8453 FixedArray::kHeaderSize));
8451 result = elements; 8454 result = elements;
8452 __ CompareRoot(result.reg(), Heap::kTheHoleValueRootIndex); 8455 __ CompareRoot(result.reg(), Heap::kTheHoleValueRootIndex);
8453 deferred->Branch(equal); 8456 deferred->Branch(equal);
8454 __ IncrementCounter(&Counters::keyed_load_inline, 1); 8457 __ IncrementCounter(COUNTERS->keyed_load_inline(), 1);
8455 8458
8456 deferred->BindExit(); 8459 deferred->BindExit();
8457 } else { 8460 } else {
8458 Comment cmnt(masm_, "[ Load from keyed Property"); 8461 Comment cmnt(masm_, "[ Load from keyed Property");
8459 result = frame_->CallKeyedLoadIC(RelocInfo::CODE_TARGET); 8462 result = frame_->CallKeyedLoadIC(RelocInfo::CODE_TARGET);
8460 // Make sure that we do not have a test instruction after the 8463 // Make sure that we do not have a test instruction after the
8461 // call. A test instruction after the call is used to 8464 // call. A test instruction after the call is used to
8462 // indicate that we have generated an inline version of the 8465 // indicate that we have generated an inline version of the
8463 // keyed load. The explicit nop instruction is here because 8466 // keyed load. The explicit nop instruction is here because
8464 // the push that follows might be peep-hole optimized away. 8467 // the push that follows might be peep-hole optimized away.
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
8533 } 8536 }
8534 8537
8535 __ bind(&in_new_space); 8538 __ bind(&in_new_space);
8536 // Bind the deferred code patch site to be able to locate the fixed 8539 // Bind the deferred code patch site to be able to locate the fixed
8537 // array map comparison. When debugging, we patch this comparison to 8540 // array map comparison. When debugging, we patch this comparison to
8538 // always fail so that we will hit the IC call in the deferred code 8541 // always fail so that we will hit the IC call in the deferred code
8539 // which will allow the debugger to break for fast case stores. 8542 // which will allow the debugger to break for fast case stores.
8540 __ bind(deferred->patch_site()); 8543 __ bind(deferred->patch_site());
8541 // Avoid using __ to ensure the distance from patch_site 8544 // Avoid using __ to ensure the distance from patch_site
8542 // to the map address is always the same. 8545 // to the map address is always the same.
8543 masm()->movq(kScratchRegister, Factory::fixed_array_map(), 8546 masm()->movq(kScratchRegister, FACTORY->fixed_array_map(),
8544 RelocInfo::EMBEDDED_OBJECT); 8547 RelocInfo::EMBEDDED_OBJECT);
8545 __ cmpq(FieldOperand(tmp.reg(), HeapObject::kMapOffset), 8548 __ cmpq(FieldOperand(tmp.reg(), HeapObject::kMapOffset),
8546 kScratchRegister); 8549 kScratchRegister);
8547 deferred->Branch(not_equal); 8550 deferred->Branch(not_equal);
8548 8551
8549 // Check that the key is within bounds. Both the key and the length of 8552 // Check that the key is within bounds. Both the key and the length of
8550 // the JSArray are smis (because the fixed array check above ensures the 8553 // the JSArray are smis (because the fixed array check above ensures the
8551 // elements are in fast case). Use unsigned comparison to handle negative 8554 // elements are in fast case). Use unsigned comparison to handle negative
8552 // keys. 8555 // keys.
8553 __ SmiCompare(FieldOperand(receiver.reg(), JSArray::kLengthOffset), 8556 __ SmiCompare(FieldOperand(receiver.reg(), JSArray::kLengthOffset),
8554 key.reg()); 8557 key.reg());
8555 deferred->Branch(below_equal); 8558 deferred->Branch(below_equal);
8556 8559
8557 // Store the value. 8560 // Store the value.
8558 SmiIndex index = 8561 SmiIndex index =
8559 masm()->SmiToIndex(kScratchRegister, key.reg(), kPointerSizeLog2); 8562 masm()->SmiToIndex(kScratchRegister, key.reg(), kPointerSizeLog2);
8560 __ movq(FieldOperand(tmp.reg(), 8563 __ movq(FieldOperand(tmp.reg(),
8561 index.reg, 8564 index.reg,
8562 index.scale, 8565 index.scale,
8563 FixedArray::kHeaderSize), 8566 FixedArray::kHeaderSize),
8564 result.reg()); 8567 result.reg());
8565 __ IncrementCounter(&Counters::keyed_store_inline, 1); 8568 __ IncrementCounter(COUNTERS->keyed_store_inline(), 1);
8566 8569
8567 deferred->BindExit(); 8570 deferred->BindExit();
8568 } else { 8571 } else {
8569 result = frame()->CallKeyedStoreIC(strict_mode_flag()); 8572 result = frame()->CallKeyedStoreIC(strict_mode_flag());
8570 // Make sure that we do not have a test instruction after the 8573 // Make sure that we do not have a test instruction after the
8571 // call. A test instruction after the call is used to 8574 // call. A test instruction after the call is used to
8572 // indicate that we have generated an inline version of the 8575 // indicate that we have generated an inline version of the
8573 // keyed store. 8576 // keyed store.
8574 __ nop(); 8577 __ nop();
8575 } 8578 }
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after
8838 } 8841 }
8839 8842
8840 #endif 8843 #endif
8841 8844
8842 8845
8843 #undef __ 8846 #undef __
8844 8847
8845 } } // namespace v8::internal 8848 } } // namespace v8::internal
8846 8849
8847 #endif // V8_TARGET_ARCH_X64 8850 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/codegen-x64.h ('k') | src/x64/cpu-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698