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

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

Issue 196133017: Experimental parser: merge r19949 (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
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/x64/frames-x64.h ('k') | src/x64/ic-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 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 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 // o rbp: our caller's frame pointer 112 // o rbp: our caller's frame pointer
113 // o rsp: stack pointer (pointing to return address) 113 // o rsp: 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-x64.h for its layout. 116 // frames-x64.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 121
122 InitializeFeedbackVector();
123
124 profiling_counter_ = isolate()->factory()->NewCell( 122 profiling_counter_ = isolate()->factory()->NewCell(
125 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate())); 123 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
126 SetFunctionPosition(function()); 124 SetFunctionPosition(function());
127 Comment cmnt(masm_, "[ function compiled by full code generator"); 125 Comment cmnt(masm_, "[ function compiled by full code generator");
128 126
129 ProfileEntryHookStub::MaybeCallEntryHook(masm_); 127 ProfileEntryHookStub::MaybeCallEntryHook(masm_);
130 128
131 #ifdef DEBUG 129 #ifdef DEBUG
132 if (strlen(FLAG_stop_at) > 0 && 130 if (strlen(FLAG_stop_at) > 0 &&
133 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { 131 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
134 __ int3(); 132 __ int3();
135 } 133 }
136 #endif 134 #endif
137 135
138 // Classic mode functions and builtins need to replace the receiver with the 136 // Sloppy mode functions and builtins need to replace the receiver with the
139 // global proxy when called as functions (without an explicit receiver 137 // global proxy when called as functions (without an explicit receiver
140 // object). 138 // object).
141 if (info->is_classic_mode() && !info->is_native()) { 139 if (info->strict_mode() == SLOPPY && !info->is_native()) {
142 Label ok; 140 Label ok;
143 // +1 for return address. 141 // +1 for return address.
144 StackArgumentsAccessor args(rsp, info->scope()->num_parameters()); 142 StackArgumentsAccessor args(rsp, info->scope()->num_parameters());
145 __ movp(rcx, args.GetReceiverOperand()); 143 __ movp(rcx, args.GetReceiverOperand());
146 144
147 __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex); 145 __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex);
148 __ j(not_equal, &ok, Label::kNear); 146 __ j(not_equal, &ok, Label::kNear);
149 147
150 __ movp(rcx, GlobalObjectOperand()); 148 __ movp(rcx, GlobalObjectOperand());
151 __ movp(rcx, FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); 149 __ movp(rcx, FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset));
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 int offset = num_parameters * kPointerSize; 235 int offset = num_parameters * kPointerSize;
238 __ lea(rdx, 236 __ lea(rdx,
239 Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset)); 237 Operand(rbp, StandardFrameConstants::kCallerSPOffset + offset));
240 __ push(rdx); 238 __ push(rdx);
241 __ Push(Smi::FromInt(num_parameters)); 239 __ Push(Smi::FromInt(num_parameters));
242 // Arguments to ArgumentsAccessStub: 240 // Arguments to ArgumentsAccessStub:
243 // function, receiver address, parameter count. 241 // function, receiver address, parameter count.
244 // The stub will rewrite receiver and parameter count if the previous 242 // The stub will rewrite receiver and parameter count if the previous
245 // stack frame was an arguments adapter frame. 243 // stack frame was an arguments adapter frame.
246 ArgumentsAccessStub::Type type; 244 ArgumentsAccessStub::Type type;
247 if (!is_classic_mode()) { 245 if (strict_mode() == STRICT) {
248 type = ArgumentsAccessStub::NEW_STRICT; 246 type = ArgumentsAccessStub::NEW_STRICT;
249 } else if (function()->has_duplicate_parameters()) { 247 } else if (function()->has_duplicate_parameters()) {
250 type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW; 248 type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
251 } else { 249 } else {
252 type = ArgumentsAccessStub::NEW_NON_STRICT_FAST; 250 type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
253 } 251 }
254 ArgumentsAccessStub stub(type); 252 ArgumentsAccessStub stub(type);
255 __ CallStub(&stub); 253 __ CallStub(&stub);
256 254
257 SetVar(arguments, rax, rbx, rdx); 255 SetVar(arguments, rax, rbx, rdx);
258 } 256 }
259 257
260 if (FLAG_trace) { 258 if (FLAG_trace) {
261 __ CallRuntime(Runtime::kTraceEnter, 0); 259 __ CallRuntime(Runtime::kTraceEnter, 0);
262 } 260 }
263 261
264 // Visit the declarations and body unless there is an illegal 262 // Visit the declarations and body unless there is an illegal
265 // redeclaration. 263 // redeclaration.
266 if (scope()->HasIllegalRedeclaration()) { 264 if (scope()->HasIllegalRedeclaration()) {
267 Comment cmnt(masm_, "[ Declarations"); 265 Comment cmnt(masm_, "[ Declarations");
268 scope()->VisitIllegalRedeclaration(this); 266 scope()->VisitIllegalRedeclaration(this);
269 267
270 } else { 268 } else {
271 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); 269 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
272 { Comment cmnt(masm_, "[ Declarations"); 270 { Comment cmnt(masm_, "[ Declarations");
273 // For named function expressions, declare the function name as a 271 // For named function expressions, declare the function name as a
274 // constant. 272 // constant.
275 if (scope()->is_function_scope() && scope()->function() != NULL) { 273 if (scope()->is_function_scope() && scope()->function() != NULL) {
276 VariableDeclaration* function = scope()->function(); 274 VariableDeclaration* function = scope()->function();
277 ASSERT(function->proxy()->var()->mode() == CONST || 275 ASSERT(function->proxy()->var()->mode() == CONST ||
278 function->proxy()->var()->mode() == CONST_HARMONY); 276 function->proxy()->var()->mode() == CONST_LEGACY);
279 ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED); 277 ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED);
280 VisitVariableDeclaration(function); 278 VisitVariableDeclaration(function);
281 } 279 }
282 VisitDeclarations(scope()->declarations()); 280 VisitDeclarations(scope()->declarations());
283 } 281 }
284 282
285 { Comment cmnt(masm_, "[ Stack check"); 283 { Comment cmnt(masm_, "[ Stack check");
286 PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); 284 PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
287 Label ok; 285 Label ok;
288 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 286 __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after
751 749
752 750
753 void FullCodeGenerator::VisitVariableDeclaration( 751 void FullCodeGenerator::VisitVariableDeclaration(
754 VariableDeclaration* declaration) { 752 VariableDeclaration* declaration) {
755 // If it was not possible to allocate the variable at compile time, we 753 // If it was not possible to allocate the variable at compile time, we
756 // need to "declare" it at runtime to make sure it actually exists in the 754 // need to "declare" it at runtime to make sure it actually exists in the
757 // local context. 755 // local context.
758 VariableProxy* proxy = declaration->proxy(); 756 VariableProxy* proxy = declaration->proxy();
759 VariableMode mode = declaration->mode(); 757 VariableMode mode = declaration->mode();
760 Variable* variable = proxy->var(); 758 Variable* variable = proxy->var();
761 bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET; 759 bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
762 switch (variable->location()) { 760 switch (variable->location()) {
763 case Variable::UNALLOCATED: 761 case Variable::UNALLOCATED:
764 globals_->Add(variable->name(), zone()); 762 globals_->Add(variable->name(), zone());
765 globals_->Add(variable->binding_needs_init() 763 globals_->Add(variable->binding_needs_init()
766 ? isolate()->factory()->the_hole_value() 764 ? isolate()->factory()->the_hole_value()
767 : isolate()->factory()->undefined_value(), 765 : isolate()->factory()->undefined_value(),
768 zone()); 766 zone());
769 break; 767 break;
770 768
771 case Variable::PARAMETER: 769 case Variable::PARAMETER:
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after
1120 __ jmp(&loop); 1118 __ jmp(&loop);
1121 1119
1122 __ bind(&no_descriptors); 1120 __ bind(&no_descriptors);
1123 __ addq(rsp, Immediate(kPointerSize)); 1121 __ addq(rsp, Immediate(kPointerSize));
1124 __ jmp(&exit); 1122 __ jmp(&exit);
1125 1123
1126 // We got a fixed array in register rax. Iterate through that. 1124 // We got a fixed array in register rax. Iterate through that.
1127 Label non_proxy; 1125 Label non_proxy;
1128 __ bind(&fixed_array); 1126 __ bind(&fixed_array);
1129 1127
1130 Handle<Object> feedback = Handle<Object>(
1131 Smi::FromInt(TypeFeedbackInfo::kForInFastCaseMarker),
1132 isolate());
1133 StoreFeedbackVectorSlot(slot, feedback);
1134
1135 // No need for a write barrier, we are storing a Smi in the feedback vector. 1128 // No need for a write barrier, we are storing a Smi in the feedback vector.
1136 __ Move(rbx, FeedbackVector()); 1129 __ Move(rbx, FeedbackVector());
1137 __ Move(FieldOperand(rbx, FixedArray::OffsetOfElementAt(slot)), 1130 __ Move(FieldOperand(rbx, FixedArray::OffsetOfElementAt(slot)),
1138 Smi::FromInt(TypeFeedbackInfo::kForInSlowCaseMarker)); 1131 TypeFeedbackInfo::MegamorphicSentinel(isolate()));
1139 __ Move(rbx, Smi::FromInt(1)); // Smi indicates slow check 1132 __ Move(rbx, Smi::FromInt(1)); // Smi indicates slow check
1140 __ movp(rcx, Operand(rsp, 0 * kPointerSize)); // Get enumerated object 1133 __ movp(rcx, Operand(rsp, 0 * kPointerSize)); // Get enumerated object
1141 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 1134 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
1142 __ CmpObjectType(rcx, LAST_JS_PROXY_TYPE, rcx); 1135 __ CmpObjectType(rcx, LAST_JS_PROXY_TYPE, rcx);
1143 __ j(above, &non_proxy); 1136 __ j(above, &non_proxy);
1144 __ Move(rbx, Smi::FromInt(0)); // Zero indicates proxy 1137 __ Move(rbx, Smi::FromInt(0)); // Zero indicates proxy
1145 __ bind(&non_proxy); 1138 __ bind(&non_proxy);
1146 __ push(rbx); // Smi 1139 __ push(rbx); // Smi
1147 __ push(rax); // Array 1140 __ push(rax); // Array
1148 __ movp(rax, FieldOperand(rax, FixedArray::kLengthOffset)); 1141 __ movp(rax, FieldOperand(rax, FixedArray::kLengthOffset));
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
1285 // space for nested functions that don't need literals cloning. If 1278 // space for nested functions that don't need literals cloning. If
1286 // we're running with the --always-opt or the --prepare-always-opt 1279 // we're running with the --always-opt or the --prepare-always-opt
1287 // flag, we need to use the runtime function so that the new function 1280 // flag, we need to use the runtime function so that the new function
1288 // we are creating here gets a chance to have its code optimized and 1281 // we are creating here gets a chance to have its code optimized and
1289 // doesn't just get a copy of the existing unoptimized code. 1282 // doesn't just get a copy of the existing unoptimized code.
1290 if (!FLAG_always_opt && 1283 if (!FLAG_always_opt &&
1291 !FLAG_prepare_always_opt && 1284 !FLAG_prepare_always_opt &&
1292 !pretenure && 1285 !pretenure &&
1293 scope()->is_function_scope() && 1286 scope()->is_function_scope() &&
1294 info->num_literals() == 0) { 1287 info->num_literals() == 0) {
1295 FastNewClosureStub stub(info->language_mode(), info->is_generator()); 1288 FastNewClosureStub stub(info->strict_mode(), info->is_generator());
1296 __ Move(rbx, info); 1289 __ Move(rbx, info);
1297 __ CallStub(&stub); 1290 __ CallStub(&stub);
1298 } else { 1291 } else {
1299 __ push(rsi); 1292 __ push(rsi);
1300 __ Push(info); 1293 __ Push(info);
1301 __ Push(pretenure 1294 __ Push(pretenure
1302 ? isolate()->factory()->true_value() 1295 ? isolate()->factory()->true_value()
1303 : isolate()->factory()->false_value()); 1296 : isolate()->factory()->false_value());
1304 __ CallRuntime(Runtime::kNewClosure, 3); 1297 __ CallRuntime(Runtime::kNewClosure, 3);
1305 } 1298 }
1306 context()->Plug(rax); 1299 context()->Plug(rax);
1307 } 1300 }
1308 1301
1309 1302
1310 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { 1303 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
1311 Comment cmnt(masm_, "[ VariableProxy"); 1304 Comment cmnt(masm_, "[ VariableProxy");
1312 EmitVariableLoad(expr); 1305 EmitVariableLoad(expr);
1313 } 1306 }
1314 1307
1315 1308
1316 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, 1309 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
1317 TypeofState typeof_state, 1310 TypeofState typeof_state,
1318 Label* slow) { 1311 Label* slow) {
1319 Register context = rsi; 1312 Register context = rsi;
1320 Register temp = rdx; 1313 Register temp = rdx;
1321 1314
1322 Scope* s = scope(); 1315 Scope* s = scope();
1323 while (s != NULL) { 1316 while (s != NULL) {
1324 if (s->num_heap_slots() > 0) { 1317 if (s->num_heap_slots() > 0) {
1325 if (s->calls_non_strict_eval()) { 1318 if (s->calls_sloppy_eval()) {
1326 // Check that extension is NULL. 1319 // Check that extension is NULL.
1327 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), 1320 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX),
1328 Immediate(0)); 1321 Immediate(0));
1329 __ j(not_equal, slow); 1322 __ j(not_equal, slow);
1330 } 1323 }
1331 // Load next context in chain. 1324 // Load next context in chain.
1332 __ movp(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); 1325 __ movp(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
1333 // Walk the rest of the chain without clobbering rsi. 1326 // Walk the rest of the chain without clobbering rsi.
1334 context = temp; 1327 context = temp;
1335 } 1328 }
1336 // If no outer scope calls eval, we do not need to check more 1329 // If no outer scope calls eval, we do not need to check more
1337 // context extensions. If we have reached an eval scope, we check 1330 // context extensions. If we have reached an eval scope, we check
1338 // all extensions from this point. 1331 // all extensions from this point.
1339 if (!s->outer_scope_calls_non_strict_eval() || s->is_eval_scope()) break; 1332 if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope()) break;
1340 s = s->outer_scope(); 1333 s = s->outer_scope();
1341 } 1334 }
1342 1335
1343 if (s != NULL && s->is_eval_scope()) { 1336 if (s != NULL && s->is_eval_scope()) {
1344 // Loop up the context chain. There is no frame effect so it is 1337 // Loop up the context chain. There is no frame effect so it is
1345 // safe to use raw labels here. 1338 // safe to use raw labels here.
1346 Label next, fast; 1339 Label next, fast;
1347 if (!context.is(temp)) { 1340 if (!context.is(temp)) {
1348 __ movp(temp, context); 1341 __ movp(temp, context);
1349 } 1342 }
(...skipping 24 matching lines...) Expand all
1374 1367
1375 1368
1376 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, 1369 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
1377 Label* slow) { 1370 Label* slow) {
1378 ASSERT(var->IsContextSlot()); 1371 ASSERT(var->IsContextSlot());
1379 Register context = rsi; 1372 Register context = rsi;
1380 Register temp = rbx; 1373 Register temp = rbx;
1381 1374
1382 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { 1375 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
1383 if (s->num_heap_slots() > 0) { 1376 if (s->num_heap_slots() > 0) {
1384 if (s->calls_non_strict_eval()) { 1377 if (s->calls_sloppy_eval()) {
1385 // Check that extension is NULL. 1378 // Check that extension is NULL.
1386 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX), 1379 __ cmpq(ContextOperand(context, Context::EXTENSION_INDEX),
1387 Immediate(0)); 1380 Immediate(0));
1388 __ j(not_equal, slow); 1381 __ j(not_equal, slow);
1389 } 1382 }
1390 __ movp(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); 1383 __ movp(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
1391 // Walk the rest of the chain without clobbering rsi. 1384 // Walk the rest of the chain without clobbering rsi.
1392 context = temp; 1385 context = temp;
1393 } 1386 }
1394 } 1387 }
(...skipping 16 matching lines...) Expand all
1411 // eval-introduced variables. Eval is used a lot without 1404 // eval-introduced variables. Eval is used a lot without
1412 // introducing variables. In those cases, we do not want to 1405 // introducing variables. In those cases, we do not want to
1413 // perform a runtime call for all variables in the scope 1406 // perform a runtime call for all variables in the scope
1414 // containing the eval. 1407 // containing the eval.
1415 if (var->mode() == DYNAMIC_GLOBAL) { 1408 if (var->mode() == DYNAMIC_GLOBAL) {
1416 EmitLoadGlobalCheckExtensions(var, typeof_state, slow); 1409 EmitLoadGlobalCheckExtensions(var, typeof_state, slow);
1417 __ jmp(done); 1410 __ jmp(done);
1418 } else if (var->mode() == DYNAMIC_LOCAL) { 1411 } else if (var->mode() == DYNAMIC_LOCAL) {
1419 Variable* local = var->local_if_not_shadowed(); 1412 Variable* local = var->local_if_not_shadowed();
1420 __ movp(rax, ContextSlotOperandCheckExtensions(local, slow)); 1413 __ movp(rax, ContextSlotOperandCheckExtensions(local, slow));
1421 if (local->mode() == LET || 1414 if (local->mode() == LET || local->mode() == CONST ||
1422 local->mode() == CONST || 1415 local->mode() == CONST_LEGACY) {
1423 local->mode() == CONST_HARMONY) {
1424 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 1416 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
1425 __ j(not_equal, done); 1417 __ j(not_equal, done);
1426 if (local->mode() == CONST) { 1418 if (local->mode() == CONST_LEGACY) {
1427 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 1419 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1428 } else { // LET || CONST_HARMONY 1420 } else { // LET || CONST
1429 __ Push(var->name()); 1421 __ Push(var->name());
1430 __ CallRuntime(Runtime::kThrowReferenceError, 1); 1422 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1431 } 1423 }
1432 } 1424 }
1433 __ jmp(done); 1425 __ jmp(done);
1434 } 1426 }
1435 } 1427 }
1436 1428
1437 1429
1438 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { 1430 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1483 // binding is initialized: 1475 // binding is initialized:
1484 // function() { f(); let x = 1; function f() { x = 2; } } 1476 // function() { f(); let x = 1; function f() { x = 2; } }
1485 // 1477 //
1486 bool skip_init_check; 1478 bool skip_init_check;
1487 if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) { 1479 if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) {
1488 skip_init_check = false; 1480 skip_init_check = false;
1489 } else { 1481 } else {
1490 // Check that we always have valid source position. 1482 // Check that we always have valid source position.
1491 ASSERT(var->initializer_position() != RelocInfo::kNoPosition); 1483 ASSERT(var->initializer_position() != RelocInfo::kNoPosition);
1492 ASSERT(proxy->position() != RelocInfo::kNoPosition); 1484 ASSERT(proxy->position() != RelocInfo::kNoPosition);
1493 skip_init_check = var->mode() != CONST && 1485 skip_init_check = var->mode() != CONST_LEGACY &&
1494 var->initializer_position() < proxy->position(); 1486 var->initializer_position() < proxy->position();
1495 } 1487 }
1496 1488
1497 if (!skip_init_check) { 1489 if (!skip_init_check) {
1498 // Let and const need a read barrier. 1490 // Let and const need a read barrier.
1499 Label done; 1491 Label done;
1500 GetVar(rax, var); 1492 GetVar(rax, var);
1501 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); 1493 __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
1502 __ j(not_equal, &done, Label::kNear); 1494 __ j(not_equal, &done, Label::kNear);
1503 if (var->mode() == LET || var->mode() == CONST_HARMONY) { 1495 if (var->mode() == LET || var->mode() == CONST) {
1504 // Throw a reference error when using an uninitialized let/const 1496 // Throw a reference error when using an uninitialized let/const
1505 // binding in harmony mode. 1497 // binding in harmony mode.
1506 __ Push(var->name()); 1498 __ Push(var->name());
1507 __ CallRuntime(Runtime::kThrowReferenceError, 1); 1499 __ CallRuntime(Runtime::kThrowReferenceError, 1);
1508 } else { 1500 } else {
1509 // Uninitalized const bindings outside of harmony mode are unholed. 1501 // Uninitalized const bindings outside of harmony mode are unholed.
1510 ASSERT(var->mode() == CONST); 1502 ASSERT(var->mode() == CONST_LEGACY);
1511 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 1503 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
1512 } 1504 }
1513 __ bind(&done); 1505 __ bind(&done);
1514 context()->Plug(rax); 1506 context()->Plug(rax);
1515 break; 1507 break;
1516 } 1508 }
1517 } 1509 }
1518 context()->Plug(var); 1510 context()->Plug(var);
1519 break; 1511 break;
1520 } 1512 }
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1605 1597
1606 expr->BuildConstantProperties(isolate()); 1598 expr->BuildConstantProperties(isolate());
1607 Handle<FixedArray> constant_properties = expr->constant_properties(); 1599 Handle<FixedArray> constant_properties = expr->constant_properties();
1608 int flags = expr->fast_elements() 1600 int flags = expr->fast_elements()
1609 ? ObjectLiteral::kFastElements 1601 ? ObjectLiteral::kFastElements
1610 : ObjectLiteral::kNoFlags; 1602 : ObjectLiteral::kNoFlags;
1611 flags |= expr->has_function() 1603 flags |= expr->has_function()
1612 ? ObjectLiteral::kHasFunction 1604 ? ObjectLiteral::kHasFunction
1613 : ObjectLiteral::kNoFlags; 1605 : ObjectLiteral::kNoFlags;
1614 int properties_count = constant_properties->length() / 2; 1606 int properties_count = constant_properties->length() / 2;
1615 if ((FLAG_track_double_fields && expr->may_store_doubles()) || 1607 if (expr->may_store_doubles() || expr->depth() > 1 || Serializer::enabled() ||
1616 expr->depth() > 1 || Serializer::enabled() ||
1617 flags != ObjectLiteral::kFastElements || 1608 flags != ObjectLiteral::kFastElements ||
1618 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { 1609 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
1619 __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1610 __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
1620 __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset)); 1611 __ push(FieldOperand(rdi, JSFunction::kLiteralsOffset));
1621 __ Push(Smi::FromInt(expr->literal_index())); 1612 __ Push(Smi::FromInt(expr->literal_index()));
1622 __ Push(constant_properties); 1613 __ Push(constant_properties);
1623 __ Push(Smi::FromInt(flags)); 1614 __ Push(Smi::FromInt(flags));
1624 __ CallRuntime(Runtime::kCreateObjectLiteral, 4); 1615 __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
1625 } else { 1616 } else {
1626 __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 1617 __ movp(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
(...skipping 755 matching lines...) Expand 10 before | Expand all | Expand 10 after
2382 CallStoreIC(); 2373 CallStoreIC();
2383 break; 2374 break;
2384 } 2375 }
2385 case KEYED_PROPERTY: { 2376 case KEYED_PROPERTY: {
2386 __ push(rax); // Preserve value. 2377 __ push(rax); // Preserve value.
2387 VisitForStackValue(prop->obj()); 2378 VisitForStackValue(prop->obj());
2388 VisitForAccumulatorValue(prop->key()); 2379 VisitForAccumulatorValue(prop->key());
2389 __ movp(rcx, rax); 2380 __ movp(rcx, rax);
2390 __ pop(rdx); 2381 __ pop(rdx);
2391 __ pop(rax); // Restore value. 2382 __ pop(rax); // Restore value.
2392 Handle<Code> ic = is_classic_mode() 2383 Handle<Code> ic = strict_mode() == SLOPPY
2393 ? isolate()->builtins()->KeyedStoreIC_Initialize() 2384 ? isolate()->builtins()->KeyedStoreIC_Initialize()
2394 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 2385 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
2395 CallIC(ic); 2386 CallIC(ic);
2396 break; 2387 break;
2397 } 2388 }
2398 } 2389 }
2399 context()->Plug(rax); 2390 context()->Plug(rax);
2400 } 2391 }
2401 2392
2402 2393
2403 void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( 2394 void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
2404 Variable* var, MemOperand location) { 2395 Variable* var, MemOperand location) {
2405 __ movp(location, rax); 2396 __ movp(location, rax);
2406 if (var->IsContextSlot()) { 2397 if (var->IsContextSlot()) {
2407 __ movp(rdx, rax); 2398 __ movp(rdx, rax);
2408 __ RecordWriteContextSlot( 2399 __ RecordWriteContextSlot(
2409 rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs); 2400 rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs);
2410 } 2401 }
2411 } 2402 }
2412 2403
2413 2404
2414 void FullCodeGenerator::EmitCallStoreContextSlot( 2405 void FullCodeGenerator::EmitCallStoreContextSlot(
2415 Handle<String> name, LanguageMode mode) { 2406 Handle<String> name, StrictMode strict_mode) {
2416 __ push(rax); // Value. 2407 __ push(rax); // Value.
2417 __ push(rsi); // Context. 2408 __ push(rsi); // Context.
2418 __ Push(name); 2409 __ Push(name);
2419 __ Push(Smi::FromInt(mode)); 2410 __ Push(Smi::FromInt(strict_mode));
2420 __ CallRuntime(Runtime::kStoreContextSlot, 4); 2411 __ CallRuntime(Runtime::kStoreContextSlot, 4);
2421 } 2412 }
2422 2413
2423 2414
2424 void FullCodeGenerator::EmitVariableAssignment(Variable* var, 2415 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
2425 Token::Value op) { 2416 Token::Value op) {
2426 if (var->IsUnallocated()) { 2417 if (var->IsUnallocated()) {
2427 // Global var, const, or let. 2418 // Global var, const, or let.
2428 __ Move(rcx, var->name()); 2419 __ Move(rcx, var->name());
2429 __ movp(rdx, GlobalObjectOperand()); 2420 __ movp(rdx, GlobalObjectOperand());
2430 CallStoreIC(); 2421 CallStoreIC();
2431 2422
2432 } else if (op == Token::INIT_CONST) { 2423 } else if (op == Token::INIT_CONST_LEGACY) {
2433 // Const initializers need a write barrier. 2424 // Const initializers need a write barrier.
2434 ASSERT(!var->IsParameter()); // No const parameters. 2425 ASSERT(!var->IsParameter()); // No const parameters.
2435 if (var->IsLookupSlot()) { 2426 if (var->IsLookupSlot()) {
2436 __ push(rax); 2427 __ push(rax);
2437 __ push(rsi); 2428 __ push(rsi);
2438 __ Push(var->name()); 2429 __ Push(var->name());
2439 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); 2430 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
2440 } else { 2431 } else {
2441 ASSERT(var->IsStackLocal() || var->IsContextSlot()); 2432 ASSERT(var->IsStackLocal() || var->IsContextSlot());
2442 Label skip; 2433 Label skip;
2443 MemOperand location = VarOperand(var, rcx); 2434 MemOperand location = VarOperand(var, rcx);
2444 __ movp(rdx, location); 2435 __ movp(rdx, location);
2445 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); 2436 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
2446 __ j(not_equal, &skip); 2437 __ j(not_equal, &skip);
2447 EmitStoreToStackLocalOrContextSlot(var, location); 2438 EmitStoreToStackLocalOrContextSlot(var, location);
2448 __ bind(&skip); 2439 __ bind(&skip);
2449 } 2440 }
2450 2441
2451 } else if (var->mode() == LET && op != Token::INIT_LET) { 2442 } else if (var->mode() == LET && op != Token::INIT_LET) {
2452 // Non-initializing assignment to let variable needs a write barrier. 2443 // Non-initializing assignment to let variable needs a write barrier.
2453 if (var->IsLookupSlot()) { 2444 if (var->IsLookupSlot()) {
2454 EmitCallStoreContextSlot(var->name(), language_mode()); 2445 EmitCallStoreContextSlot(var->name(), strict_mode());
2455 } else { 2446 } else {
2456 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 2447 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
2457 Label assign; 2448 Label assign;
2458 MemOperand location = VarOperand(var, rcx); 2449 MemOperand location = VarOperand(var, rcx);
2459 __ movp(rdx, location); 2450 __ movp(rdx, location);
2460 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); 2451 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
2461 __ j(not_equal, &assign, Label::kNear); 2452 __ j(not_equal, &assign, Label::kNear);
2462 __ Push(var->name()); 2453 __ Push(var->name());
2463 __ CallRuntime(Runtime::kThrowReferenceError, 1); 2454 __ CallRuntime(Runtime::kThrowReferenceError, 1);
2464 __ bind(&assign); 2455 __ bind(&assign);
2465 EmitStoreToStackLocalOrContextSlot(var, location); 2456 EmitStoreToStackLocalOrContextSlot(var, location);
2466 } 2457 }
2467 2458
2468 } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) { 2459 } else if (!var->is_const_mode() || op == Token::INIT_CONST) {
2469 // Assignment to var or initializing assignment to let/const 2460 // Assignment to var or initializing assignment to let/const
2470 // in harmony mode. 2461 // in harmony mode.
2471 if (var->IsLookupSlot()) { 2462 if (var->IsLookupSlot()) {
2472 EmitCallStoreContextSlot(var->name(), language_mode()); 2463 EmitCallStoreContextSlot(var->name(), strict_mode());
2473 } else { 2464 } else {
2474 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 2465 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
2475 MemOperand location = VarOperand(var, rcx); 2466 MemOperand location = VarOperand(var, rcx);
2476 if (generate_debug_code_ && op == Token::INIT_LET) { 2467 if (generate_debug_code_ && op == Token::INIT_LET) {
2477 // Check for an uninitialized let binding. 2468 // Check for an uninitialized let binding.
2478 __ movp(rdx, location); 2469 __ movp(rdx, location);
2479 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); 2470 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
2480 __ Check(equal, kLetBindingReInitialization); 2471 __ Check(equal, kLetBindingReInitialization);
2481 } 2472 }
2482 EmitStoreToStackLocalOrContextSlot(var, location); 2473 EmitStoreToStackLocalOrContextSlot(var, location);
(...skipping 20 matching lines...) Expand all
2503 } 2494 }
2504 2495
2505 2496
2506 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 2497 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
2507 // Assignment to a property, using a keyed store IC. 2498 // Assignment to a property, using a keyed store IC.
2508 2499
2509 __ pop(rcx); 2500 __ pop(rcx);
2510 __ pop(rdx); 2501 __ pop(rdx);
2511 // Record source code position before IC call. 2502 // Record source code position before IC call.
2512 SetSourcePosition(expr->position()); 2503 SetSourcePosition(expr->position());
2513 Handle<Code> ic = is_classic_mode() 2504 Handle<Code> ic = strict_mode() == SLOPPY
2514 ? isolate()->builtins()->KeyedStoreIC_Initialize() 2505 ? isolate()->builtins()->KeyedStoreIC_Initialize()
2515 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 2506 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
2516 CallIC(ic, expr->AssignmentFeedbackId()); 2507 CallIC(ic, expr->AssignmentFeedbackId());
2517 2508
2518 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 2509 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2519 context()->Plug(rax); 2510 context()->Plug(rax);
2520 } 2511 }
2521 2512
2522 2513
2523 void FullCodeGenerator::VisitProperty(Property* expr) { 2514 void FullCodeGenerator::VisitProperty(Property* expr) {
(...skipping 29 matching lines...) Expand all
2553 int arg_count = args->length(); 2544 int arg_count = args->length();
2554 2545
2555 CallFunctionFlags flags; 2546 CallFunctionFlags flags;
2556 // Get the target function; 2547 // Get the target function;
2557 if (callee->IsVariableProxy()) { 2548 if (callee->IsVariableProxy()) {
2558 { StackValueContext context(this); 2549 { StackValueContext context(this);
2559 EmitVariableLoad(callee->AsVariableProxy()); 2550 EmitVariableLoad(callee->AsVariableProxy());
2560 PrepareForBailout(callee, NO_REGISTERS); 2551 PrepareForBailout(callee, NO_REGISTERS);
2561 } 2552 }
2562 // Push undefined as receiver. This is patched in the method prologue if it 2553 // Push undefined as receiver. This is patched in the method prologue if it
2563 // is a classic mode method. 2554 // is a sloppy mode method.
2564 __ Push(isolate()->factory()->undefined_value()); 2555 __ Push(isolate()->factory()->undefined_value());
2565 flags = NO_CALL_FUNCTION_FLAGS; 2556 flags = NO_CALL_FUNCTION_FLAGS;
2566 } else { 2557 } else {
2567 // Load the function from the receiver. 2558 // Load the function from the receiver.
2568 ASSERT(callee->IsProperty()); 2559 ASSERT(callee->IsProperty());
2569 __ movp(rax, Operand(rsp, 0)); 2560 __ movp(rax, Operand(rsp, 0));
2570 EmitNamedPropertyLoad(callee->AsProperty()); 2561 EmitNamedPropertyLoad(callee->AsProperty());
2571 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); 2562 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2572 // Push the target function under the receiver. 2563 // Push the target function under the receiver.
2573 __ push(Operand(rsp, 0)); 2564 __ push(Operand(rsp, 0));
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
2643 ZoneList<Expression*>* args = expr->arguments(); 2634 ZoneList<Expression*>* args = expr->arguments();
2644 int arg_count = args->length(); 2635 int arg_count = args->length();
2645 { PreservePositionScope scope(masm()->positions_recorder()); 2636 { PreservePositionScope scope(masm()->positions_recorder());
2646 for (int i = 0; i < arg_count; i++) { 2637 for (int i = 0; i < arg_count; i++) {
2647 VisitForStackValue(args->at(i)); 2638 VisitForStackValue(args->at(i));
2648 } 2639 }
2649 } 2640 }
2650 // Record source position for debugger. 2641 // Record source position for debugger.
2651 SetSourcePosition(expr->position()); 2642 SetSourcePosition(expr->position());
2652 2643
2653 Handle<Object> uninitialized =
2654 TypeFeedbackInfo::UninitializedSentinel(isolate());
2655 StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized);
2656 __ Move(rbx, FeedbackVector()); 2644 __ Move(rbx, FeedbackVector());
2657 __ Move(rdx, Smi::FromInt(expr->CallFeedbackSlot())); 2645 __ Move(rdx, Smi::FromInt(expr->CallFeedbackSlot()));
2658 2646
2659 // Record call targets in unoptimized code. 2647 // Record call targets in unoptimized code.
2660 CallFunctionStub stub(arg_count, RECORD_CALL_TARGET); 2648 CallFunctionStub stub(arg_count, RECORD_CALL_TARGET);
2661 __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); 2649 __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
2662 __ CallStub(&stub); 2650 __ CallStub(&stub);
2663 RecordJSReturnSite(expr); 2651 RecordJSReturnSite(expr);
2664 // Restore context register. 2652 // Restore context register.
2665 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2653 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2666 // Discard the function left on TOS. 2654 // Discard the function left on TOS.
2667 context()->DropAndPlug(1, rax); 2655 context()->DropAndPlug(1, rax);
2668 } 2656 }
2669 2657
2670 2658
2671 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { 2659 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
2672 // Push copy of the first argument or undefined if it doesn't exist. 2660 // Push copy of the first argument or undefined if it doesn't exist.
2673 if (arg_count > 0) { 2661 if (arg_count > 0) {
2674 __ push(Operand(rsp, arg_count * kPointerSize)); 2662 __ push(Operand(rsp, arg_count * kPointerSize));
2675 } else { 2663 } else {
2676 __ PushRoot(Heap::kUndefinedValueRootIndex); 2664 __ PushRoot(Heap::kUndefinedValueRootIndex);
2677 } 2665 }
2678 2666
2679 // Push the receiver of the enclosing function and do runtime call. 2667 // Push the receiver of the enclosing function and do runtime call.
2680 StackArgumentsAccessor args(rbp, info_->scope()->num_parameters()); 2668 StackArgumentsAccessor args(rbp, info_->scope()->num_parameters());
2681 __ push(args.GetReceiverOperand()); 2669 __ push(args.GetReceiverOperand());
2682 2670
2683 // Push the language mode. 2671 // Push the language mode.
2684 __ Push(Smi::FromInt(language_mode())); 2672 __ Push(Smi::FromInt(strict_mode()));
2685 2673
2686 // Push the start position of the scope the calls resides in. 2674 // Push the start position of the scope the calls resides in.
2687 __ Push(Smi::FromInt(scope()->start_position())); 2675 __ Push(Smi::FromInt(scope()->start_position()));
2688 2676
2689 // Do the runtime call. 2677 // Do the runtime call.
2690 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); 2678 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
2691 } 2679 }
2692 2680
2693 2681
2694 void FullCodeGenerator::VisitCall(Call* expr) { 2682 void FullCodeGenerator::VisitCall(Call* expr) {
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
2823 2811
2824 // Call the construct call builtin that handles allocation and 2812 // Call the construct call builtin that handles allocation and
2825 // constructor invocation. 2813 // constructor invocation.
2826 SetSourcePosition(expr->position()); 2814 SetSourcePosition(expr->position());
2827 2815
2828 // Load function and argument count into rdi and rax. 2816 // Load function and argument count into rdi and rax.
2829 __ Set(rax, arg_count); 2817 __ Set(rax, arg_count);
2830 __ movp(rdi, Operand(rsp, arg_count * kPointerSize)); 2818 __ movp(rdi, Operand(rsp, arg_count * kPointerSize));
2831 2819
2832 // Record call targets in unoptimized code, but not in the snapshot. 2820 // Record call targets in unoptimized code, but not in the snapshot.
2833 Handle<Object> uninitialized =
2834 TypeFeedbackInfo::UninitializedSentinel(isolate());
2835 StoreFeedbackVectorSlot(expr->CallNewFeedbackSlot(), uninitialized);
2836 __ Move(rbx, FeedbackVector()); 2821 __ Move(rbx, FeedbackVector());
2837 __ Move(rdx, Smi::FromInt(expr->CallNewFeedbackSlot())); 2822 __ Move(rdx, Smi::FromInt(expr->CallNewFeedbackSlot()));
2838 2823
2839 CallConstructStub stub(RECORD_CALL_TARGET); 2824 CallConstructStub stub(RECORD_CALL_TARGET);
2840 __ Call(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL); 2825 __ Call(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL);
2841 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); 2826 PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
2842 context()->Plug(rax); 2827 context()->Plug(rax);
2843 } 2828 }
2844 2829
2845 2830
(...skipping 1327 matching lines...) Expand 10 before | Expand all | Expand 10 after
4173 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 4158 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
4174 switch (expr->op()) { 4159 switch (expr->op()) {
4175 case Token::DELETE: { 4160 case Token::DELETE: {
4176 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); 4161 Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
4177 Property* property = expr->expression()->AsProperty(); 4162 Property* property = expr->expression()->AsProperty();
4178 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 4163 VariableProxy* proxy = expr->expression()->AsVariableProxy();
4179 4164
4180 if (property != NULL) { 4165 if (property != NULL) {
4181 VisitForStackValue(property->obj()); 4166 VisitForStackValue(property->obj());
4182 VisitForStackValue(property->key()); 4167 VisitForStackValue(property->key());
4183 StrictModeFlag strict_mode_flag = (language_mode() == CLASSIC_MODE) 4168 __ Push(Smi::FromInt(strict_mode()));
4184 ? kNonStrictMode : kStrictMode;
4185 __ Push(Smi::FromInt(strict_mode_flag));
4186 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 4169 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
4187 context()->Plug(rax); 4170 context()->Plug(rax);
4188 } else if (proxy != NULL) { 4171 } else if (proxy != NULL) {
4189 Variable* var = proxy->var(); 4172 Variable* var = proxy->var();
4190 // Delete of an unqualified identifier is disallowed in strict mode 4173 // Delete of an unqualified identifier is disallowed in strict mode
4191 // but "delete this" is allowed. 4174 // but "delete this" is allowed.
4192 ASSERT(language_mode() == CLASSIC_MODE || var->is_this()); 4175 ASSERT(strict_mode() == SLOPPY || var->is_this());
4193 if (var->IsUnallocated()) { 4176 if (var->IsUnallocated()) {
4194 __ push(GlobalObjectOperand()); 4177 __ push(GlobalObjectOperand());
4195 __ Push(var->name()); 4178 __ Push(var->name());
4196 __ Push(Smi::FromInt(kNonStrictMode)); 4179 __ Push(Smi::FromInt(SLOPPY));
4197 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 4180 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
4198 context()->Plug(rax); 4181 context()->Plug(rax);
4199 } else if (var->IsStackAllocated() || var->IsContextSlot()) { 4182 } else if (var->IsStackAllocated() || var->IsContextSlot()) {
4200 // Result of deleting non-global variables is false. 'this' is 4183 // Result of deleting non-global variables is false. 'this' is
4201 // not really a variable, though we implement it as one. The 4184 // not really a variable, though we implement it as one. The
4202 // subexpression does not have side effects. 4185 // subexpression does not have side effects.
4203 context()->Plug(var->is_this()); 4186 context()->Plug(var->is_this());
4204 } else { 4187 } else {
4205 // Non-global variable. Call the runtime to try to delete from the 4188 // Non-global variable. Call the runtime to try to delete from the
4206 // context where the variable was introduced. 4189 // context where the variable was introduced.
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
4448 context()->PlugTOS(); 4431 context()->PlugTOS();
4449 } 4432 }
4450 } else { 4433 } else {
4451 context()->Plug(rax); 4434 context()->Plug(rax);
4452 } 4435 }
4453 break; 4436 break;
4454 } 4437 }
4455 case KEYED_PROPERTY: { 4438 case KEYED_PROPERTY: {
4456 __ pop(rcx); 4439 __ pop(rcx);
4457 __ pop(rdx); 4440 __ pop(rdx);
4458 Handle<Code> ic = is_classic_mode() 4441 Handle<Code> ic = strict_mode() == SLOPPY
4459 ? isolate()->builtins()->KeyedStoreIC_Initialize() 4442 ? isolate()->builtins()->KeyedStoreIC_Initialize()
4460 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 4443 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
4461 CallIC(ic, expr->CountStoreFeedbackId()); 4444 CallIC(ic, expr->CountStoreFeedbackId());
4462 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4445 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4463 if (expr->is_postfix()) { 4446 if (expr->is_postfix()) {
4464 if (!context()->IsEffect()) { 4447 if (!context()->IsEffect()) {
4465 context()->PlugTOS(); 4448 context()->PlugTOS();
4466 } 4449 }
4467 } else { 4450 } else {
4468 context()->Plug(rax); 4451 context()->Plug(rax);
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after
4869 // nop 4852 // nop
4870 // nop 4853 // nop
4871 // call <on-stack replacment> 4854 // call <on-stack replacment>
4872 // ok: 4855 // ok:
4873 *jns_instr_address = kNopByteOne; 4856 *jns_instr_address = kNopByteOne;
4874 *jns_offset_address = kNopByteTwo; 4857 *jns_offset_address = kNopByteTwo;
4875 break; 4858 break;
4876 } 4859 }
4877 4860
4878 Assembler::set_target_address_at(call_target_address, 4861 Assembler::set_target_address_at(call_target_address,
4862 unoptimized_code,
4879 replacement_code->entry()); 4863 replacement_code->entry());
4880 unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch( 4864 unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
4881 unoptimized_code, call_target_address, replacement_code); 4865 unoptimized_code, call_target_address, replacement_code);
4882 } 4866 }
4883 4867
4884 4868
4885 BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState( 4869 BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState(
4886 Isolate* isolate, 4870 Isolate* isolate,
4887 Code* unoptimized_code, 4871 Code* unoptimized_code,
4888 Address pc) { 4872 Address pc) {
4889 Address call_target_address = pc - kIntSize; 4873 Address call_target_address = pc - kIntSize;
4890 Address jns_instr_address = call_target_address - 3; 4874 Address jns_instr_address = call_target_address - 3;
4891 ASSERT_EQ(kCallInstruction, *(call_target_address - 1)); 4875 ASSERT_EQ(kCallInstruction, *(call_target_address - 1));
4892 4876
4893 if (*jns_instr_address == kJnsInstruction) { 4877 if (*jns_instr_address == kJnsInstruction) {
4894 ASSERT_EQ(kJnsOffset, *(call_target_address - 2)); 4878 ASSERT_EQ(kJnsOffset, *(call_target_address - 2));
4895 ASSERT_EQ(isolate->builtins()->InterruptCheck()->entry(), 4879 ASSERT_EQ(isolate->builtins()->InterruptCheck()->entry(),
4896 Assembler::target_address_at(call_target_address)); 4880 Assembler::target_address_at(call_target_address,
4881 unoptimized_code));
4897 return INTERRUPT; 4882 return INTERRUPT;
4898 } 4883 }
4899 4884
4900 ASSERT_EQ(kNopByteOne, *jns_instr_address); 4885 ASSERT_EQ(kNopByteOne, *jns_instr_address);
4901 ASSERT_EQ(kNopByteTwo, *(call_target_address - 2)); 4886 ASSERT_EQ(kNopByteTwo, *(call_target_address - 2));
4902 4887
4903 if (Assembler::target_address_at(call_target_address) == 4888 if (Assembler::target_address_at(call_target_address,
4889 unoptimized_code) ==
4904 isolate->builtins()->OnStackReplacement()->entry()) { 4890 isolate->builtins()->OnStackReplacement()->entry()) {
4905 return ON_STACK_REPLACEMENT; 4891 return ON_STACK_REPLACEMENT;
4906 } 4892 }
4907 4893
4908 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), 4894 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(),
4909 Assembler::target_address_at(call_target_address)); 4895 Assembler::target_address_at(call_target_address,
4896 unoptimized_code));
4910 return OSR_AFTER_STACK_CHECK; 4897 return OSR_AFTER_STACK_CHECK;
4911 } 4898 }
4912 4899
4913 4900
4914 } } // namespace v8::internal 4901 } } // namespace v8::internal
4915 4902
4916 #endif // V8_TARGET_ARCH_X64 4903 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/frames-x64.h ('k') | src/x64/ic-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698