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

Side by Side Diff: src/ia32/full-codegen-ia32.cc

Issue 181453002: Reset trunk to 3.24.35.4 (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: Created 6 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/ia32/disasm-ia32.cc ('k') | src/ia32/ic-ia32.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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 // o esi: our context 111 // o esi: our context
112 // o ebp: our caller's frame pointer 112 // o ebp: our caller's frame pointer
113 // o esp: stack pointer (pointing to return address) 113 // o esp: stack pointer (pointing to return address)
114 // 114 //
115 // The function builds a JS frame. Please see JavaScriptFrameConstants in 115 // The function builds a JS frame. Please see JavaScriptFrameConstants in
116 // frames-ia32.h for its layout. 116 // frames-ia32.h for its layout.
117 void FullCodeGenerator::Generate() { 117 void FullCodeGenerator::Generate() {
118 CompilationInfo* info = info_; 118 CompilationInfo* info = info_;
119 handler_table_ = 119 handler_table_ =
120 isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED); 120 isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
121
122 InitializeFeedbackVector();
123
124 profiling_counter_ = isolate()->factory()->NewCell( 121 profiling_counter_ = isolate()->factory()->NewCell(
125 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate())); 122 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
126 SetFunctionPosition(function()); 123 SetFunctionPosition(function());
127 Comment cmnt(masm_, "[ function compiled by full code generator"); 124 Comment cmnt(masm_, "[ function compiled by full code generator");
128 125
129 ProfileEntryHookStub::MaybeCallEntryHook(masm_); 126 ProfileEntryHookStub::MaybeCallEntryHook(masm_);
130 127
131 #ifdef DEBUG 128 #ifdef DEBUG
132 if (strlen(FLAG_stop_at) > 0 && 129 if (strlen(FLAG_stop_at) > 0 &&
133 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { 130 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after
622 if (false_label_ != fall_through_) __ jmp(false_label_); 619 if (false_label_ != fall_through_) __ jmp(false_label_);
623 } 620 }
624 } 621 }
625 622
626 623
627 void FullCodeGenerator::DoTest(Expression* condition, 624 void FullCodeGenerator::DoTest(Expression* condition,
628 Label* if_true, 625 Label* if_true,
629 Label* if_false, 626 Label* if_false,
630 Label* fall_through) { 627 Label* fall_through) {
631 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); 628 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate());
632 CallIC(ic, condition->test_id()); 629 CallIC(ic, NOT_CONTEXTUAL, condition->test_id());
633 __ test(result_register(), result_register()); 630 __ test(result_register(), result_register());
634 // The stub returns nonzero for true. 631 // The stub returns nonzero for true.
635 Split(not_zero, if_true, if_false, fall_through); 632 Split(not_zero, if_true, if_false, fall_through);
636 } 633 }
637 634
638 635
639 void FullCodeGenerator::Split(Condition cc, 636 void FullCodeGenerator::Split(Condition cc,
640 Label* if_true, 637 Label* if_true,
641 Label* if_false, 638 Label* if_false,
642 Label* fall_through) { 639 Label* fall_through) {
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
973 __ cmp(edx, eax); 970 __ cmp(edx, eax);
974 __ j(not_equal, &next_test); 971 __ j(not_equal, &next_test);
975 __ Drop(1); // Switch value is no longer needed. 972 __ Drop(1); // Switch value is no longer needed.
976 __ jmp(clause->body_target()); 973 __ jmp(clause->body_target());
977 __ bind(&slow_case); 974 __ bind(&slow_case);
978 } 975 }
979 976
980 // Record position before stub call for type feedback. 977 // Record position before stub call for type feedback.
981 SetSourcePosition(clause->position()); 978 SetSourcePosition(clause->position());
982 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); 979 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT);
983 CallIC(ic, clause->CompareId()); 980 CallIC(ic, NOT_CONTEXTUAL, clause->CompareId());
984 patch_site.EmitPatchInfo(); 981 patch_site.EmitPatchInfo();
985 982
986 Label skip; 983 Label skip;
987 __ jmp(&skip, Label::kNear); 984 __ jmp(&skip, Label::kNear);
988 PrepareForBailout(clause, TOS_REG); 985 PrepareForBailout(clause, TOS_REG);
989 __ cmp(eax, isolate()->factory()->true_value()); 986 __ cmp(eax, isolate()->factory()->true_value());
990 __ j(not_equal, &next_test); 987 __ j(not_equal, &next_test);
991 __ Drop(1); 988 __ Drop(1);
992 __ jmp(clause->body_target()); 989 __ jmp(clause->body_target());
993 __ bind(&skip); 990 __ bind(&skip);
(...skipping 23 matching lines...) Expand all
1017 VisitStatements(clause->statements()); 1014 VisitStatements(clause->statements());
1018 } 1015 }
1019 1016
1020 __ bind(nested_statement.break_label()); 1017 __ bind(nested_statement.break_label());
1021 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 1018 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1022 } 1019 }
1023 1020
1024 1021
1025 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { 1022 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
1026 Comment cmnt(masm_, "[ ForInStatement"); 1023 Comment cmnt(masm_, "[ ForInStatement");
1027 int slot = stmt->ForInFeedbackSlot();
1028
1029 SetStatementPosition(stmt); 1024 SetStatementPosition(stmt);
1030 1025
1031 Label loop, exit; 1026 Label loop, exit;
1032 ForIn loop_statement(this, stmt); 1027 ForIn loop_statement(this, stmt);
1033 increment_loop_depth(); 1028 increment_loop_depth();
1034 1029
1035 // Get the object to enumerate over. If the object is null or undefined, skip 1030 // Get the object to enumerate over. If the object is null or undefined, skip
1036 // over the loop. See ECMA-262 version 5, section 12.6.4. 1031 // over the loop. See ECMA-262 version 5, section 12.6.4.
1037 VisitForAccumulatorValue(stmt->enumerable()); 1032 VisitForAccumulatorValue(stmt->enumerable());
1038 __ cmp(eax, isolate()->factory()->undefined_value()); 1033 __ cmp(eax, isolate()->factory()->undefined_value());
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1097 __ jmp(&loop); 1092 __ jmp(&loop);
1098 1093
1099 __ bind(&no_descriptors); 1094 __ bind(&no_descriptors);
1100 __ add(esp, Immediate(kPointerSize)); 1095 __ add(esp, Immediate(kPointerSize));
1101 __ jmp(&exit); 1096 __ jmp(&exit);
1102 1097
1103 // We got a fixed array in register eax. Iterate through that. 1098 // We got a fixed array in register eax. Iterate through that.
1104 Label non_proxy; 1099 Label non_proxy;
1105 __ bind(&fixed_array); 1100 __ bind(&fixed_array);
1106 1101
1107 Handle<Object> feedback = Handle<Object>( 1102 Handle<Cell> cell = isolate()->factory()->NewCell(
1108 Smi::FromInt(TypeFeedbackInfo::kForInFastCaseMarker), 1103 Handle<Object>(Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker),
1109 isolate()); 1104 isolate()));
1110 StoreFeedbackVectorSlot(slot, feedback); 1105 RecordTypeFeedbackCell(stmt->ForInFeedbackId(), cell);
1111 1106 __ LoadHeapObject(ebx, cell);
1112 // No need for a write barrier, we are storing a Smi in the feedback vector. 1107 __ mov(FieldOperand(ebx, Cell::kValueOffset),
1113 __ LoadHeapObject(ebx, FeedbackVector()); 1108 Immediate(Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker)));
1114 __ mov(FieldOperand(ebx, FixedArray::OffsetOfElementAt(slot)),
1115 Immediate(Smi::FromInt(TypeFeedbackInfo::kForInSlowCaseMarker)));
1116 1109
1117 __ mov(ebx, Immediate(Smi::FromInt(1))); // Smi indicates slow check 1110 __ mov(ebx, Immediate(Smi::FromInt(1))); // Smi indicates slow check
1118 __ mov(ecx, Operand(esp, 0 * kPointerSize)); // Get enumerated object 1111 __ mov(ecx, Operand(esp, 0 * kPointerSize)); // Get enumerated object
1119 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 1112 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
1120 __ CmpObjectType(ecx, LAST_JS_PROXY_TYPE, ecx); 1113 __ CmpObjectType(ecx, LAST_JS_PROXY_TYPE, ecx);
1121 __ j(above, &non_proxy); 1114 __ j(above, &non_proxy);
1122 __ Set(ebx, Immediate(Smi::FromInt(0))); // Zero indicates proxy 1115 __ Set(ebx, Immediate(Smi::FromInt(0))); // Zero indicates proxy
1123 __ bind(&non_proxy); 1116 __ bind(&non_proxy);
1124 __ push(ebx); // Smi 1117 __ push(ebx); // Smi
1125 __ push(eax); // Array 1118 __ push(eax); // Array
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
1412 1405
1413 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { 1406 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
1414 // Record position before possible IC call. 1407 // Record position before possible IC call.
1415 SetSourcePosition(proxy->position()); 1408 SetSourcePosition(proxy->position());
1416 Variable* var = proxy->var(); 1409 Variable* var = proxy->var();
1417 1410
1418 // Three cases: global variables, lookup variables, and all other types of 1411 // Three cases: global variables, lookup variables, and all other types of
1419 // variables. 1412 // variables.
1420 switch (var->location()) { 1413 switch (var->location()) {
1421 case Variable::UNALLOCATED: { 1414 case Variable::UNALLOCATED: {
1422 Comment cmnt(masm_, "[ Global variable"); 1415 Comment cmnt(masm_, "Global variable");
1423 // Use inline caching. Variable name is passed in ecx and the global 1416 // Use inline caching. Variable name is passed in ecx and the global
1424 // object in eax. 1417 // object in eax.
1425 __ mov(edx, GlobalObjectOperand()); 1418 __ mov(edx, GlobalObjectOperand());
1426 __ mov(ecx, var->name()); 1419 __ mov(ecx, var->name());
1427 CallLoadIC(CONTEXTUAL); 1420 CallLoadIC(CONTEXTUAL);
1428 context()->Plug(eax); 1421 context()->Plug(eax);
1429 break; 1422 break;
1430 } 1423 }
1431 1424
1432 case Variable::PARAMETER: 1425 case Variable::PARAMETER:
1433 case Variable::LOCAL: 1426 case Variable::LOCAL:
1434 case Variable::CONTEXT: { 1427 case Variable::CONTEXT: {
1435 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" 1428 Comment cmnt(masm_, var->IsContextSlot()
1436 : "[ Stack variable"); 1429 ? "Context variable"
1430 : "Stack variable");
1437 if (var->binding_needs_init()) { 1431 if (var->binding_needs_init()) {
1438 // var->scope() may be NULL when the proxy is located in eval code and 1432 // var->scope() may be NULL when the proxy is located in eval code and
1439 // refers to a potential outside binding. Currently those bindings are 1433 // refers to a potential outside binding. Currently those bindings are
1440 // always looked up dynamically, i.e. in that case 1434 // always looked up dynamically, i.e. in that case
1441 // var->location() == LOOKUP. 1435 // var->location() == LOOKUP.
1442 // always holds. 1436 // always holds.
1443 ASSERT(var->scope() != NULL); 1437 ASSERT(var->scope() != NULL);
1444 1438
1445 // Check if the binding really needs an initialization check. The check 1439 // Check if the binding really needs an initialization check. The check
1446 // can be skipped in the following situation: we have a LET or CONST 1440 // can be skipped in the following situation: we have a LET or CONST
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1488 __ bind(&done); 1482 __ bind(&done);
1489 context()->Plug(eax); 1483 context()->Plug(eax);
1490 break; 1484 break;
1491 } 1485 }
1492 } 1486 }
1493 context()->Plug(var); 1487 context()->Plug(var);
1494 break; 1488 break;
1495 } 1489 }
1496 1490
1497 case Variable::LOOKUP: { 1491 case Variable::LOOKUP: {
1498 Comment cmnt(masm_, "[ Lookup variable");
1499 Label done, slow; 1492 Label done, slow;
1500 // Generate code for loading from variables potentially shadowed 1493 // Generate code for loading from variables potentially shadowed
1501 // by eval-introduced variables. 1494 // by eval-introduced variables.
1502 EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done); 1495 EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done);
1503 __ bind(&slow); 1496 __ bind(&slow);
1497 Comment cmnt(masm_, "Lookup variable");
1504 __ push(esi); // Context. 1498 __ push(esi); // Context.
1505 __ push(Immediate(var->name())); 1499 __ push(Immediate(var->name()));
1506 __ CallRuntime(Runtime::kLoadContextSlot, 2); 1500 __ CallRuntime(Runtime::kLoadContextSlot, 2);
1507 __ bind(&done); 1501 __ bind(&done);
1508 context()->Plug(eax); 1502 context()->Plug(eax);
1509 break; 1503 break;
1510 } 1504 }
1511 } 1505 }
1512 } 1506 }
1513 1507
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
1632 UNREACHABLE(); 1626 UNREACHABLE();
1633 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1627 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1634 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 1628 ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
1635 // Fall through. 1629 // Fall through.
1636 case ObjectLiteral::Property::COMPUTED: 1630 case ObjectLiteral::Property::COMPUTED:
1637 if (key->value()->IsInternalizedString()) { 1631 if (key->value()->IsInternalizedString()) {
1638 if (property->emit_store()) { 1632 if (property->emit_store()) {
1639 VisitForAccumulatorValue(value); 1633 VisitForAccumulatorValue(value);
1640 __ mov(ecx, Immediate(key->value())); 1634 __ mov(ecx, Immediate(key->value()));
1641 __ mov(edx, Operand(esp, 0)); 1635 __ mov(edx, Operand(esp, 0));
1642 CallStoreIC(key->LiteralFeedbackId()); 1636 CallStoreIC(NOT_CONTEXTUAL, key->LiteralFeedbackId());
1643 PrepareForBailoutForId(key->id(), NO_REGISTERS); 1637 PrepareForBailoutForId(key->id(), NO_REGISTERS);
1644 } else { 1638 } else {
1645 VisitForEffect(value); 1639 VisitForEffect(value);
1646 } 1640 }
1647 break; 1641 break;
1648 } 1642 }
1649 __ push(Operand(esp, 0)); // Duplicate receiver. 1643 __ push(Operand(esp, 0)); // Duplicate receiver.
1650 VisitForStackValue(key); 1644 VisitForStackValue(key);
1651 VisitForStackValue(value); 1645 VisitForStackValue(value);
1652 if (property->emit_store()) { 1646 if (property->emit_store()) {
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after
2046 __ bind(&l_next); 2040 __ bind(&l_next);
2047 __ mov(ecx, isolate()->factory()->next_string()); // "next" 2041 __ mov(ecx, isolate()->factory()->next_string()); // "next"
2048 __ push(ecx); 2042 __ push(ecx);
2049 __ push(Operand(esp, 2 * kPointerSize)); // iter 2043 __ push(Operand(esp, 2 * kPointerSize)); // iter
2050 __ push(eax); // received 2044 __ push(eax); // received
2051 2045
2052 // result = receiver[f](arg); 2046 // result = receiver[f](arg);
2053 __ bind(&l_call); 2047 __ bind(&l_call);
2054 __ mov(edx, Operand(esp, kPointerSize)); 2048 __ mov(edx, Operand(esp, kPointerSize));
2055 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); 2049 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
2056 CallIC(ic, TypeFeedbackId::None()); 2050 CallIC(ic, NOT_CONTEXTUAL, TypeFeedbackId::None());
2057 __ mov(edi, eax); 2051 __ mov(edi, eax);
2058 __ mov(Operand(esp, 2 * kPointerSize), edi); 2052 __ mov(Operand(esp, 2 * kPointerSize), edi);
2059 CallFunctionStub stub(1, CALL_AS_METHOD); 2053 CallFunctionStub stub(1, CALL_AS_METHOD);
2060 __ CallStub(&stub); 2054 __ CallStub(&stub);
2061 2055
2062 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2056 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2063 __ Drop(1); // The function is still on the stack; drop it. 2057 __ Drop(1); // The function is still on the stack; drop it.
2064 2058
2065 // if (!result.done) goto l_try; 2059 // if (!result.done) goto l_try;
2066 __ bind(&l_loop); 2060 __ bind(&l_loop);
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
2236 Literal* key = prop->key()->AsLiteral(); 2230 Literal* key = prop->key()->AsLiteral();
2237 ASSERT(!key->value()->IsSmi()); 2231 ASSERT(!key->value()->IsSmi());
2238 __ mov(ecx, Immediate(key->value())); 2232 __ mov(ecx, Immediate(key->value()));
2239 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); 2233 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
2240 } 2234 }
2241 2235
2242 2236
2243 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 2237 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
2244 SetSourcePosition(prop->position()); 2238 SetSourcePosition(prop->position());
2245 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); 2239 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
2246 CallIC(ic, prop->PropertyFeedbackId()); 2240 CallIC(ic, NOT_CONTEXTUAL, prop->PropertyFeedbackId());
2247 } 2241 }
2248 2242
2249 2243
2250 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, 2244 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
2251 Token::Value op, 2245 Token::Value op,
2252 OverwriteMode mode, 2246 OverwriteMode mode,
2253 Expression* left, 2247 Expression* left,
2254 Expression* right) { 2248 Expression* right) {
2255 // Do combined smi check of the operands. Left operand is on the 2249 // Do combined smi check of the operands. Left operand is on the
2256 // stack. Right operand is in eax. 2250 // stack. Right operand is in eax.
2257 Label smi_case, done, stub_call; 2251 Label smi_case, done, stub_call;
2258 __ pop(edx); 2252 __ pop(edx);
2259 __ mov(ecx, eax); 2253 __ mov(ecx, eax);
2260 __ or_(eax, edx); 2254 __ or_(eax, edx);
2261 JumpPatchSite patch_site(masm_); 2255 JumpPatchSite patch_site(masm_);
2262 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear); 2256 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear);
2263 2257
2264 __ bind(&stub_call); 2258 __ bind(&stub_call);
2265 __ mov(eax, ecx); 2259 __ mov(eax, ecx);
2266 BinaryOpICStub stub(op, mode); 2260 BinaryOpICStub stub(op, mode);
2267 CallIC(stub.GetCode(isolate()), expr->BinaryOperationFeedbackId()); 2261 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL,
2262 expr->BinaryOperationFeedbackId());
2268 patch_site.EmitPatchInfo(); 2263 patch_site.EmitPatchInfo();
2269 __ jmp(&done, Label::kNear); 2264 __ jmp(&done, Label::kNear);
2270 2265
2271 // Smi case. 2266 // Smi case.
2272 __ bind(&smi_case); 2267 __ bind(&smi_case);
2273 __ mov(eax, edx); // Copy left operand in case of a stub call. 2268 __ mov(eax, edx); // Copy left operand in case of a stub call.
2274 2269
2275 switch (op) { 2270 switch (op) {
2276 case Token::SAR: 2271 case Token::SAR:
2277 __ SmiUntag(eax); 2272 __ SmiUntag(eax);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
2342 context()->Plug(eax); 2337 context()->Plug(eax);
2343 } 2338 }
2344 2339
2345 2340
2346 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, 2341 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
2347 Token::Value op, 2342 Token::Value op,
2348 OverwriteMode mode) { 2343 OverwriteMode mode) {
2349 __ pop(edx); 2344 __ pop(edx);
2350 BinaryOpICStub stub(op, mode); 2345 BinaryOpICStub stub(op, mode);
2351 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. 2346 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
2352 CallIC(stub.GetCode(isolate()), expr->BinaryOperationFeedbackId()); 2347 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL,
2348 expr->BinaryOperationFeedbackId());
2353 patch_site.EmitPatchInfo(); 2349 patch_site.EmitPatchInfo();
2354 context()->Plug(eax); 2350 context()->Plug(eax);
2355 } 2351 }
2356 2352
2357 2353
2358 void FullCodeGenerator::EmitAssignment(Expression* expr) { 2354 void FullCodeGenerator::EmitAssignment(Expression* expr) {
2359 // Invalid left-hand sides are rewritten by the parser to have a 'throw 2355 // Invalid left-hand sides are rewritten by the parser to have a 'throw
2360 // ReferenceError' on the left-hand side. 2356 // ReferenceError' on the left-hand side.
2361 if (!expr->IsValidLeftHandSide()) { 2357 if (!expr->IsValidLeftHandSide()) {
2362 VisitForEffect(expr); 2358 VisitForEffect(expr);
(...skipping 17 matching lines...) Expand all
2380 EffectContext context(this); 2376 EffectContext context(this);
2381 EmitVariableAssignment(var, Token::ASSIGN); 2377 EmitVariableAssignment(var, Token::ASSIGN);
2382 break; 2378 break;
2383 } 2379 }
2384 case NAMED_PROPERTY: { 2380 case NAMED_PROPERTY: {
2385 __ push(eax); // Preserve value. 2381 __ push(eax); // Preserve value.
2386 VisitForAccumulatorValue(prop->obj()); 2382 VisitForAccumulatorValue(prop->obj());
2387 __ mov(edx, eax); 2383 __ mov(edx, eax);
2388 __ pop(eax); // Restore value. 2384 __ pop(eax); // Restore value.
2389 __ mov(ecx, prop->key()->AsLiteral()->value()); 2385 __ mov(ecx, prop->key()->AsLiteral()->value());
2390 CallStoreIC(); 2386 CallStoreIC(NOT_CONTEXTUAL);
2391 break; 2387 break;
2392 } 2388 }
2393 case KEYED_PROPERTY: { 2389 case KEYED_PROPERTY: {
2394 __ push(eax); // Preserve value. 2390 __ push(eax); // Preserve value.
2395 VisitForStackValue(prop->obj()); 2391 VisitForStackValue(prop->obj());
2396 VisitForAccumulatorValue(prop->key()); 2392 VisitForAccumulatorValue(prop->key());
2397 __ mov(ecx, eax); 2393 __ mov(ecx, eax);
2398 __ pop(edx); // Receiver. 2394 __ pop(edx); // Receiver.
2399 __ pop(eax); // Restore value. 2395 __ pop(eax); // Restore value.
2400 Handle<Code> ic = is_classic_mode() 2396 Handle<Code> ic = is_classic_mode()
2401 ? isolate()->builtins()->KeyedStoreIC_Initialize() 2397 ? isolate()->builtins()->KeyedStoreIC_Initialize()
2402 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 2398 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
2403 CallIC(ic); 2399 CallIC(ic);
2404 break; 2400 break;
2405 } 2401 }
2406 } 2402 }
2407 context()->Plug(eax); 2403 context()->Plug(eax);
2408 } 2404 }
2409 2405
2410 2406
2411 void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
2412 Variable* var, MemOperand location) {
2413 __ mov(location, eax);
2414 if (var->IsContextSlot()) {
2415 __ mov(edx, eax);
2416 int offset = Context::SlotOffset(var->index());
2417 __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs);
2418 }
2419 }
2420
2421
2422 void FullCodeGenerator::EmitCallStoreContextSlot(
2423 Handle<String> name, LanguageMode mode) {
2424 __ push(eax); // Value.
2425 __ push(esi); // Context.
2426 __ push(Immediate(name));
2427 __ push(Immediate(Smi::FromInt(mode)));
2428 __ CallRuntime(Runtime::kStoreContextSlot, 4);
2429 }
2430
2431
2432 void FullCodeGenerator::EmitVariableAssignment(Variable* var, 2407 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
2433 Token::Value op) { 2408 Token::Value op) {
2434 if (var->IsUnallocated()) { 2409 if (var->IsUnallocated()) {
2435 // Global var, const, or let. 2410 // Global var, const, or let.
2436 __ mov(ecx, var->name()); 2411 __ mov(ecx, var->name());
2437 __ mov(edx, GlobalObjectOperand()); 2412 __ mov(edx, GlobalObjectOperand());
2438 CallStoreIC(); 2413 CallStoreIC(CONTEXTUAL);
2439
2440 } else if (op == Token::INIT_CONST) { 2414 } else if (op == Token::INIT_CONST) {
2441 // Const initializers need a write barrier. 2415 // Const initializers need a write barrier.
2442 ASSERT(!var->IsParameter()); // No const parameters. 2416 ASSERT(!var->IsParameter()); // No const parameters.
2443 if (var->IsLookupSlot()) { 2417 if (var->IsStackLocal()) {
2418 Label skip;
2419 __ mov(edx, StackOperand(var));
2420 __ cmp(edx, isolate()->factory()->the_hole_value());
2421 __ j(not_equal, &skip);
2422 __ mov(StackOperand(var), eax);
2423 __ bind(&skip);
2424 } else {
2425 ASSERT(var->IsContextSlot() || var->IsLookupSlot());
2426 // Like var declarations, const declarations are hoisted to function
2427 // scope. However, unlike var initializers, const initializers are
2428 // able to drill a hole to that function context, even from inside a
2429 // 'with' context. We thus bypass the normal static scope lookup for
2430 // var->IsContextSlot().
2444 __ push(eax); 2431 __ push(eax);
2445 __ push(esi); 2432 __ push(esi);
2446 __ push(Immediate(var->name())); 2433 __ push(Immediate(var->name()));
2447 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); 2434 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
2448 } else {
2449 ASSERT(var->IsStackLocal() || var->IsContextSlot());
2450 Label skip;
2451 MemOperand location = VarOperand(var, ecx);
2452 __ mov(edx, location);
2453 __ cmp(edx, isolate()->factory()->the_hole_value());
2454 __ j(not_equal, &skip, Label::kNear);
2455 EmitStoreToStackLocalOrContextSlot(var, location);
2456 __ bind(&skip);
2457 } 2435 }
2458 2436
2459 } else if (var->mode() == LET && op != Token::INIT_LET) { 2437 } else if (var->mode() == LET && op != Token::INIT_LET) {
2460 // Non-initializing assignment to let variable needs a write barrier. 2438 // Non-initializing assignment to let variable needs a write barrier.
2461 if (var->IsLookupSlot()) { 2439 if (var->IsLookupSlot()) {
2462 EmitCallStoreContextSlot(var->name(), language_mode()); 2440 __ push(eax); // Value.
2441 __ push(esi); // Context.
2442 __ push(Immediate(var->name()));
2443 __ push(Immediate(Smi::FromInt(language_mode())));
2444 __ CallRuntime(Runtime::kStoreContextSlot, 4);
2463 } else { 2445 } else {
2464 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 2446 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
2465 Label assign; 2447 Label assign;
2466 MemOperand location = VarOperand(var, ecx); 2448 MemOperand location = VarOperand(var, ecx);
2467 __ mov(edx, location); 2449 __ mov(edx, location);
2468 __ cmp(edx, isolate()->factory()->the_hole_value()); 2450 __ cmp(edx, isolate()->factory()->the_hole_value());
2469 __ j(not_equal, &assign, Label::kNear); 2451 __ j(not_equal, &assign, Label::kNear);
2470 __ push(Immediate(var->name())); 2452 __ push(Immediate(var->name()));
2471 __ CallRuntime(Runtime::kThrowReferenceError, 1); 2453 __ CallRuntime(Runtime::kThrowReferenceError, 1);
2472 __ bind(&assign); 2454 __ bind(&assign);
2473 EmitStoreToStackLocalOrContextSlot(var, location); 2455 __ mov(location, eax);
2456 if (var->IsContextSlot()) {
2457 __ mov(edx, eax);
2458 int offset = Context::SlotOffset(var->index());
2459 __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs);
2460 }
2474 } 2461 }
2475 2462
2476 } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) { 2463 } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) {
2477 // Assignment to var or initializing assignment to let/const 2464 // Assignment to var or initializing assignment to let/const
2478 // in harmony mode. 2465 // in harmony mode.
2479 if (var->IsLookupSlot()) { 2466 if (var->IsStackAllocated() || var->IsContextSlot()) {
2480 EmitCallStoreContextSlot(var->name(), language_mode());
2481 } else {
2482 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
2483 MemOperand location = VarOperand(var, ecx); 2467 MemOperand location = VarOperand(var, ecx);
2484 if (generate_debug_code_ && op == Token::INIT_LET) { 2468 if (generate_debug_code_ && op == Token::INIT_LET) {
2485 // Check for an uninitialized let binding. 2469 // Check for an uninitialized let binding.
2486 __ mov(edx, location); 2470 __ mov(edx, location);
2487 __ cmp(edx, isolate()->factory()->the_hole_value()); 2471 __ cmp(edx, isolate()->factory()->the_hole_value());
2488 __ Check(equal, kLetBindingReInitialization); 2472 __ Check(equal, kLetBindingReInitialization);
2489 } 2473 }
2490 EmitStoreToStackLocalOrContextSlot(var, location); 2474 // Perform the assignment.
2475 __ mov(location, eax);
2476 if (var->IsContextSlot()) {
2477 __ mov(edx, eax);
2478 int offset = Context::SlotOffset(var->index());
2479 __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs);
2480 }
2481 } else {
2482 ASSERT(var->IsLookupSlot());
2483 __ push(eax); // Value.
2484 __ push(esi); // Context.
2485 __ push(Immediate(var->name()));
2486 __ push(Immediate(Smi::FromInt(language_mode())));
2487 __ CallRuntime(Runtime::kStoreContextSlot, 4);
2491 } 2488 }
2492 } 2489 }
2493 // Non-initializing assignments to consts are ignored. 2490 // Non-initializing assignments to consts are ignored.
2494 } 2491 }
2495 2492
2496 2493
2497 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 2494 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
2498 // Assignment to a property, using a named store IC. 2495 // Assignment to a property, using a named store IC.
2499 // eax : value 2496 // eax : value
2500 // esp[0] : receiver 2497 // esp[0] : receiver
2501 2498
2502 Property* prop = expr->target()->AsProperty(); 2499 Property* prop = expr->target()->AsProperty();
2503 ASSERT(prop != NULL); 2500 ASSERT(prop != NULL);
2504 ASSERT(prop->key()->AsLiteral() != NULL); 2501 ASSERT(prop->key()->AsLiteral() != NULL);
2505 2502
2506 // Record source code position before IC call. 2503 // Record source code position before IC call.
2507 SetSourcePosition(expr->position()); 2504 SetSourcePosition(expr->position());
2508 __ mov(ecx, prop->key()->AsLiteral()->value()); 2505 __ mov(ecx, prop->key()->AsLiteral()->value());
2509 __ pop(edx); 2506 __ pop(edx);
2510 CallStoreIC(expr->AssignmentFeedbackId()); 2507 CallStoreIC(NOT_CONTEXTUAL, expr->AssignmentFeedbackId());
2511 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 2508 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2512 context()->Plug(eax); 2509 context()->Plug(eax);
2513 } 2510 }
2514 2511
2515 2512
2516 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 2513 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
2517 // Assignment to a property, using a keyed store IC. 2514 // Assignment to a property, using a keyed store IC.
2518 // eax : value 2515 // eax : value
2519 // esp[0] : key 2516 // esp[0] : key
2520 // esp[kPointerSize] : receiver 2517 // esp[kPointerSize] : receiver
2521 2518
2522 __ pop(ecx); // Key. 2519 __ pop(ecx); // Key.
2523 __ pop(edx); 2520 __ pop(edx);
2524 // Record source code position before IC call. 2521 // Record source code position before IC call.
2525 SetSourcePosition(expr->position()); 2522 SetSourcePosition(expr->position());
2526 Handle<Code> ic = is_classic_mode() 2523 Handle<Code> ic = is_classic_mode()
2527 ? isolate()->builtins()->KeyedStoreIC_Initialize() 2524 ? isolate()->builtins()->KeyedStoreIC_Initialize()
2528 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 2525 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
2529 CallIC(ic, expr->AssignmentFeedbackId()); 2526 CallIC(ic, NOT_CONTEXTUAL, expr->AssignmentFeedbackId());
2530 2527
2531 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 2528 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2532 context()->Plug(eax); 2529 context()->Plug(eax);
2533 } 2530 }
2534 2531
2535 2532
2536 void FullCodeGenerator::VisitProperty(Property* expr) { 2533 void FullCodeGenerator::VisitProperty(Property* expr) {
2537 Comment cmnt(masm_, "[ Property"); 2534 Comment cmnt(masm_, "[ Property");
2538 Expression* key = expr->key(); 2535 Expression* key = expr->key();
2539 2536
2540 if (key->IsPropertyName()) { 2537 if (key->IsPropertyName()) {
2541 VisitForAccumulatorValue(expr->obj()); 2538 VisitForAccumulatorValue(expr->obj());
2542 __ mov(edx, result_register()); 2539 __ mov(edx, result_register());
2543 EmitNamedPropertyLoad(expr); 2540 EmitNamedPropertyLoad(expr);
2544 PrepareForBailoutForId(expr->LoadId(), TOS_REG); 2541 PrepareForBailoutForId(expr->LoadId(), TOS_REG);
2545 context()->Plug(eax); 2542 context()->Plug(eax);
2546 } else { 2543 } else {
2547 VisitForStackValue(expr->obj()); 2544 VisitForStackValue(expr->obj());
2548 VisitForAccumulatorValue(expr->key()); 2545 VisitForAccumulatorValue(expr->key());
2549 __ pop(edx); // Object. 2546 __ pop(edx); // Object.
2550 __ mov(ecx, result_register()); // Key. 2547 __ mov(ecx, result_register()); // Key.
2551 EmitKeyedPropertyLoad(expr); 2548 EmitKeyedPropertyLoad(expr);
2552 context()->Plug(eax); 2549 context()->Plug(eax);
2553 } 2550 }
2554 } 2551 }
2555 2552
2556 2553
2557 void FullCodeGenerator::CallIC(Handle<Code> code, 2554 void FullCodeGenerator::CallIC(Handle<Code> code,
2555 ContextualMode mode,
2558 TypeFeedbackId ast_id) { 2556 TypeFeedbackId ast_id) {
2559 ic_total_count_++; 2557 ic_total_count_++;
2558 ASSERT(mode != CONTEXTUAL || ast_id.IsNone());
2560 __ call(code, RelocInfo::CODE_TARGET, ast_id); 2559 __ call(code, RelocInfo::CODE_TARGET, ast_id);
2561 } 2560 }
2562 2561
2563 2562
2564 2563
2565 2564
2566 // Code common for calls using the IC. 2565 // Code common for calls using the IC.
2567 void FullCodeGenerator::EmitCallWithIC(Call* expr) { 2566 void FullCodeGenerator::EmitCallWithIC(Call* expr) {
2568 Expression* callee = expr->expression(); 2567 Expression* callee = expr->expression();
2569 ZoneList<Expression*>* args = expr->arguments(); 2568 ZoneList<Expression*>* args = expr->arguments();
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
2662 int arg_count = args->length(); 2661 int arg_count = args->length();
2663 { PreservePositionScope scope(masm()->positions_recorder()); 2662 { PreservePositionScope scope(masm()->positions_recorder());
2664 for (int i = 0; i < arg_count; i++) { 2663 for (int i = 0; i < arg_count; i++) {
2665 VisitForStackValue(args->at(i)); 2664 VisitForStackValue(args->at(i));
2666 } 2665 }
2667 } 2666 }
2668 // Record source position for debugger. 2667 // Record source position for debugger.
2669 SetSourcePosition(expr->position()); 2668 SetSourcePosition(expr->position());
2670 2669
2671 Handle<Object> uninitialized = 2670 Handle<Object> uninitialized =
2672 TypeFeedbackInfo::UninitializedSentinel(isolate()); 2671 TypeFeedbackCells::UninitializedSentinel(isolate());
2673 StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized); 2672 Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized);
2674 __ LoadHeapObject(ebx, FeedbackVector()); 2673 RecordTypeFeedbackCell(expr->CallFeedbackId(), cell);
2675 __ mov(edx, Immediate(Smi::FromInt(expr->CallFeedbackSlot()))); 2674 __ mov(ebx, cell);
2676 2675
2677 // Record call targets in unoptimized code. 2676 // Record call targets in unoptimized code.
2678 CallFunctionStub stub(arg_count, RECORD_CALL_TARGET); 2677 CallFunctionStub stub(arg_count, RECORD_CALL_TARGET);
2679 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); 2678 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
2680 __ CallStub(&stub); 2679 __ CallStub(&stub, expr->CallFeedbackId());
2681 2680
2682 RecordJSReturnSite(expr); 2681 RecordJSReturnSite(expr);
2683 // Restore context register. 2682 // Restore context register.
2684 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2683 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2685 context()->DropAndPlug(1, eax); 2684 context()->DropAndPlug(1, eax);
2686 } 2685 }
2687 2686
2688 2687
2689 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { 2688 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
2690 // Push copy of the first argument or undefined if it doesn't exist. 2689 // Push copy of the first argument or undefined if it doesn't exist.
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
2842 // Call the construct call builtin that handles allocation and 2841 // Call the construct call builtin that handles allocation and
2843 // constructor invocation. 2842 // constructor invocation.
2844 SetSourcePosition(expr->position()); 2843 SetSourcePosition(expr->position());
2845 2844
2846 // Load function and argument count into edi and eax. 2845 // Load function and argument count into edi and eax.
2847 __ Set(eax, Immediate(arg_count)); 2846 __ Set(eax, Immediate(arg_count));
2848 __ mov(edi, Operand(esp, arg_count * kPointerSize)); 2847 __ mov(edi, Operand(esp, arg_count * kPointerSize));
2849 2848
2850 // Record call targets in unoptimized code. 2849 // Record call targets in unoptimized code.
2851 Handle<Object> uninitialized = 2850 Handle<Object> uninitialized =
2852 TypeFeedbackInfo::UninitializedSentinel(isolate()); 2851 TypeFeedbackCells::UninitializedSentinel(isolate());
2853 StoreFeedbackVectorSlot(expr->CallNewFeedbackSlot(), uninitialized); 2852 Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized);
2854 __ LoadHeapObject(ebx, FeedbackVector()); 2853 RecordTypeFeedbackCell(expr->CallNewFeedbackId(), cell);
2855 __ mov(edx, Immediate(Smi::FromInt(expr->CallNewFeedbackSlot()))); 2854 __ mov(ebx, cell);
2856 2855
2857 CallConstructStub stub(RECORD_CALL_TARGET); 2856 CallConstructStub stub(RECORD_CALL_TARGET);
2858 __ call(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL); 2857 __ call(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL);
2859 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); 2858 PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
2860 context()->Plug(eax); 2859 context()->Plug(eax);
2861 } 2860 }
2862 2861
2863 2862
2864 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { 2863 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
2865 ZoneList<Expression*>* args = expr->arguments(); 2864 ZoneList<Expression*>* args = expr->arguments();
(...skipping 1544 matching lines...) Expand 10 before | Expand all | Expand 10 after
4410 } 4409 }
4411 4410
4412 // Record position before stub call. 4411 // Record position before stub call.
4413 SetSourcePosition(expr->position()); 4412 SetSourcePosition(expr->position());
4414 4413
4415 // Call stub for +1/-1. 4414 // Call stub for +1/-1.
4416 __ bind(&stub_call); 4415 __ bind(&stub_call);
4417 __ mov(edx, eax); 4416 __ mov(edx, eax);
4418 __ mov(eax, Immediate(Smi::FromInt(1))); 4417 __ mov(eax, Immediate(Smi::FromInt(1)));
4419 BinaryOpICStub stub(expr->binary_op(), NO_OVERWRITE); 4418 BinaryOpICStub stub(expr->binary_op(), NO_OVERWRITE);
4420 CallIC(stub.GetCode(isolate()), expr->CountBinOpFeedbackId()); 4419 CallIC(stub.GetCode(isolate()),
4420 NOT_CONTEXTUAL,
4421 expr->CountBinOpFeedbackId());
4421 patch_site.EmitPatchInfo(); 4422 patch_site.EmitPatchInfo();
4422 __ bind(&done); 4423 __ bind(&done);
4423 4424
4424 // Store the value returned in eax. 4425 // Store the value returned in eax.
4425 switch (assign_type) { 4426 switch (assign_type) {
4426 case VARIABLE: 4427 case VARIABLE:
4427 if (expr->is_postfix()) { 4428 if (expr->is_postfix()) {
4428 // Perform the assignment as if via '='. 4429 // Perform the assignment as if via '='.
4429 { EffectContext context(this); 4430 { EffectContext context(this);
4430 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 4431 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
(...skipping 10 matching lines...) Expand all
4441 // Perform the assignment as if via '='. 4442 // Perform the assignment as if via '='.
4442 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 4443 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
4443 Token::ASSIGN); 4444 Token::ASSIGN);
4444 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4445 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4445 context()->Plug(eax); 4446 context()->Plug(eax);
4446 } 4447 }
4447 break; 4448 break;
4448 case NAMED_PROPERTY: { 4449 case NAMED_PROPERTY: {
4449 __ mov(ecx, prop->key()->AsLiteral()->value()); 4450 __ mov(ecx, prop->key()->AsLiteral()->value());
4450 __ pop(edx); 4451 __ pop(edx);
4451 CallStoreIC(expr->CountStoreFeedbackId()); 4452 CallStoreIC(NOT_CONTEXTUAL, expr->CountStoreFeedbackId());
4452 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4453 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4453 if (expr->is_postfix()) { 4454 if (expr->is_postfix()) {
4454 if (!context()->IsEffect()) { 4455 if (!context()->IsEffect()) {
4455 context()->PlugTOS(); 4456 context()->PlugTOS();
4456 } 4457 }
4457 } else { 4458 } else {
4458 context()->Plug(eax); 4459 context()->Plug(eax);
4459 } 4460 }
4460 break; 4461 break;
4461 } 4462 }
4462 case KEYED_PROPERTY: { 4463 case KEYED_PROPERTY: {
4463 __ pop(ecx); 4464 __ pop(ecx);
4464 __ pop(edx); 4465 __ pop(edx);
4465 Handle<Code> ic = is_classic_mode() 4466 Handle<Code> ic = is_classic_mode()
4466 ? isolate()->builtins()->KeyedStoreIC_Initialize() 4467 ? isolate()->builtins()->KeyedStoreIC_Initialize()
4467 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 4468 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
4468 CallIC(ic, expr->CountStoreFeedbackId()); 4469 CallIC(ic, NOT_CONTEXTUAL, expr->CountStoreFeedbackId());
4469 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4470 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4470 if (expr->is_postfix()) { 4471 if (expr->is_postfix()) {
4471 // Result is on the stack 4472 // Result is on the stack
4472 if (!context()->IsEffect()) { 4473 if (!context()->IsEffect()) {
4473 context()->PlugTOS(); 4474 context()->PlugTOS();
4474 } 4475 }
4475 } else { 4476 } else {
4476 context()->Plug(eax); 4477 context()->Plug(eax);
4477 } 4478 }
4478 break; 4479 break;
4479 } 4480 }
4480 } 4481 }
4481 } 4482 }
4482 4483
4483 4484
4484 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { 4485 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
4485 VariableProxy* proxy = expr->AsVariableProxy(); 4486 VariableProxy* proxy = expr->AsVariableProxy();
4486 ASSERT(!context()->IsEffect()); 4487 ASSERT(!context()->IsEffect());
4487 ASSERT(!context()->IsTest()); 4488 ASSERT(!context()->IsTest());
4488 4489
4489 if (proxy != NULL && proxy->var()->IsUnallocated()) { 4490 if (proxy != NULL && proxy->var()->IsUnallocated()) {
4490 Comment cmnt(masm_, "[ Global variable"); 4491 Comment cmnt(masm_, "Global variable");
4491 __ mov(edx, GlobalObjectOperand()); 4492 __ mov(edx, GlobalObjectOperand());
4492 __ mov(ecx, Immediate(proxy->name())); 4493 __ mov(ecx, Immediate(proxy->name()));
4493 // Use a regular load, not a contextual load, to avoid a reference 4494 // Use a regular load, not a contextual load, to avoid a reference
4494 // error. 4495 // error.
4495 CallLoadIC(NOT_CONTEXTUAL); 4496 CallLoadIC(NOT_CONTEXTUAL);
4496 PrepareForBailout(expr, TOS_REG); 4497 PrepareForBailout(expr, TOS_REG);
4497 context()->Plug(eax); 4498 context()->Plug(eax);
4498 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { 4499 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
4499 Comment cmnt(masm_, "[ Lookup slot");
4500 Label done, slow; 4500 Label done, slow;
4501 4501
4502 // Generate code for loading from variables potentially shadowed 4502 // Generate code for loading from variables potentially shadowed
4503 // by eval-introduced variables. 4503 // by eval-introduced variables.
4504 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); 4504 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done);
4505 4505
4506 __ bind(&slow); 4506 __ bind(&slow);
4507 __ push(esi); 4507 __ push(esi);
4508 __ push(Immediate(proxy->name())); 4508 __ push(Immediate(proxy->name()));
4509 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 4509 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
4648 __ or_(ecx, eax); 4648 __ or_(ecx, eax);
4649 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear); 4649 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear);
4650 __ cmp(edx, eax); 4650 __ cmp(edx, eax);
4651 Split(cc, if_true, if_false, NULL); 4651 Split(cc, if_true, if_false, NULL);
4652 __ bind(&slow_case); 4652 __ bind(&slow_case);
4653 } 4653 }
4654 4654
4655 // Record position and call the compare IC. 4655 // Record position and call the compare IC.
4656 SetSourcePosition(expr->position()); 4656 SetSourcePosition(expr->position());
4657 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); 4657 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op);
4658 CallIC(ic, expr->CompareOperationFeedbackId()); 4658 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId());
4659 patch_site.EmitPatchInfo(); 4659 patch_site.EmitPatchInfo();
4660 4660
4661 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4661 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4662 __ test(eax, eax); 4662 __ test(eax, eax);
4663 Split(cc, if_true, if_false, fall_through); 4663 Split(cc, if_true, if_false, fall_through);
4664 } 4664 }
4665 } 4665 }
4666 4666
4667 // Convert the result of the comparison into one expected for this 4667 // Convert the result of the comparison into one expected for this
4668 // expression's context. 4668 // expression's context.
(...skipping 15 matching lines...) Expand all
4684 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4684 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4685 4685
4686 Handle<Object> nil_value = nil == kNullValue 4686 Handle<Object> nil_value = nil == kNullValue
4687 ? isolate()->factory()->null_value() 4687 ? isolate()->factory()->null_value()
4688 : isolate()->factory()->undefined_value(); 4688 : isolate()->factory()->undefined_value();
4689 if (expr->op() == Token::EQ_STRICT) { 4689 if (expr->op() == Token::EQ_STRICT) {
4690 __ cmp(eax, nil_value); 4690 __ cmp(eax, nil_value);
4691 Split(equal, if_true, if_false, fall_through); 4691 Split(equal, if_true, if_false, fall_through);
4692 } else { 4692 } else {
4693 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); 4693 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil);
4694 CallIC(ic, expr->CompareOperationFeedbackId()); 4694 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId());
4695 __ test(eax, eax); 4695 __ test(eax, eax);
4696 Split(not_zero, if_true, if_false, fall_through); 4696 Split(not_zero, if_true, if_false, fall_through);
4697 } 4697 }
4698 context()->Plug(if_true, if_false); 4698 context()->Plug(if_true, if_false);
4699 } 4699 }
4700 4700
4701 4701
4702 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { 4702 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
4703 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 4703 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
4704 context()->Plug(eax); 4704 context()->Plug(eax);
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
4912 4912
4913 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), 4913 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(),
4914 Assembler::target_address_at(call_target_address)); 4914 Assembler::target_address_at(call_target_address));
4915 return OSR_AFTER_STACK_CHECK; 4915 return OSR_AFTER_STACK_CHECK;
4916 } 4916 }
4917 4917
4918 4918
4919 } } // namespace v8::internal 4919 } } // namespace v8::internal
4920 4920
4921 #endif // V8_TARGET_ARCH_IA32 4921 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/disasm-ia32.cc ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698