| OLD | NEW |
| 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 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 // o sp: stack pointer | 132 // o sp: stack pointer |
| 133 // o ra: return address | 133 // o ra: return address |
| 134 // | 134 // |
| 135 // The function builds a JS frame. Please see JavaScriptFrameConstants in | 135 // The function builds a JS frame. Please see JavaScriptFrameConstants in |
| 136 // frames-mips.h for its layout. | 136 // frames-mips.h for its layout. |
| 137 void FullCodeGenerator::Generate() { | 137 void FullCodeGenerator::Generate() { |
| 138 CompilationInfo* info = info_; | 138 CompilationInfo* info = info_; |
| 139 handler_table_ = | 139 handler_table_ = |
| 140 isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED); | 140 isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED); |
| 141 | 141 |
| 142 InitializeFeedbackVector(); | |
| 143 | |
| 144 profiling_counter_ = isolate()->factory()->NewCell( | 142 profiling_counter_ = isolate()->factory()->NewCell( |
| 145 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate())); | 143 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate())); |
| 146 SetFunctionPosition(function()); | 144 SetFunctionPosition(function()); |
| 147 Comment cmnt(masm_, "[ function compiled by full code generator"); | 145 Comment cmnt(masm_, "[ function compiled by full code generator"); |
| 148 | 146 |
| 149 ProfileEntryHookStub::MaybeCallEntryHook(masm_); | 147 ProfileEntryHookStub::MaybeCallEntryHook(masm_); |
| 150 | 148 |
| 151 #ifdef DEBUG | 149 #ifdef DEBUG |
| 152 if (strlen(FLAG_stop_at) > 0 && | 150 if (strlen(FLAG_stop_at) > 0 && |
| 153 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { | 151 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { |
| 154 __ stop("stop-at"); | 152 __ stop("stop-at"); |
| 155 } | 153 } |
| 156 #endif | 154 #endif |
| 157 | 155 |
| 158 // Classic mode functions and builtins need to replace the receiver with the | 156 // Sloppy mode functions and builtins need to replace the receiver with the |
| 159 // global proxy when called as functions (without an explicit receiver | 157 // global proxy when called as functions (without an explicit receiver |
| 160 // object). | 158 // object). |
| 161 if (info->is_classic_mode() && !info->is_native()) { | 159 if (info->strict_mode() == SLOPPY && !info->is_native()) { |
| 162 Label ok; | 160 Label ok; |
| 163 int receiver_offset = info->scope()->num_parameters() * kPointerSize; | 161 int receiver_offset = info->scope()->num_parameters() * kPointerSize; |
| 164 __ lw(at, MemOperand(sp, receiver_offset)); | 162 __ lw(at, MemOperand(sp, receiver_offset)); |
| 165 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); | 163 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); |
| 166 __ Branch(&ok, ne, a2, Operand(at)); | 164 __ Branch(&ok, ne, a2, Operand(at)); |
| 167 | 165 |
| 168 __ lw(a2, GlobalObjectOperand()); | 166 __ lw(a2, GlobalObjectOperand()); |
| 169 __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalReceiverOffset)); | 167 __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalReceiverOffset)); |
| 170 | 168 |
| 171 __ sw(a2, MemOperand(sp, receiver_offset)); | 169 __ sw(a2, MemOperand(sp, receiver_offset)); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 266 __ Addu(a2, fp, | 264 __ Addu(a2, fp, |
| 267 Operand(StandardFrameConstants::kCallerSPOffset + offset)); | 265 Operand(StandardFrameConstants::kCallerSPOffset + offset)); |
| 268 __ li(a1, Operand(Smi::FromInt(num_parameters))); | 266 __ li(a1, Operand(Smi::FromInt(num_parameters))); |
| 269 __ Push(a3, a2, a1); | 267 __ Push(a3, a2, a1); |
| 270 | 268 |
| 271 // Arguments to ArgumentsAccessStub: | 269 // Arguments to ArgumentsAccessStub: |
| 272 // function, receiver address, parameter count. | 270 // function, receiver address, parameter count. |
| 273 // The stub will rewrite receiever and parameter count if the previous | 271 // The stub will rewrite receiever and parameter count if the previous |
| 274 // stack frame was an arguments adapter frame. | 272 // stack frame was an arguments adapter frame. |
| 275 ArgumentsAccessStub::Type type; | 273 ArgumentsAccessStub::Type type; |
| 276 if (!is_classic_mode()) { | 274 if (strict_mode() == STRICT) { |
| 277 type = ArgumentsAccessStub::NEW_STRICT; | 275 type = ArgumentsAccessStub::NEW_STRICT; |
| 278 } else if (function()->has_duplicate_parameters()) { | 276 } else if (function()->has_duplicate_parameters()) { |
| 279 type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW; | 277 type = ArgumentsAccessStub::NEW_SLOPPY_SLOW; |
| 280 } else { | 278 } else { |
| 281 type = ArgumentsAccessStub::NEW_NON_STRICT_FAST; | 279 type = ArgumentsAccessStub::NEW_SLOPPY_FAST; |
| 282 } | 280 } |
| 283 ArgumentsAccessStub stub(type); | 281 ArgumentsAccessStub stub(type); |
| 284 __ CallStub(&stub); | 282 __ CallStub(&stub); |
| 285 | 283 |
| 286 SetVar(arguments, v0, a1, a2); | 284 SetVar(arguments, v0, a1, a2); |
| 287 } | 285 } |
| 288 | 286 |
| 289 if (FLAG_trace) { | 287 if (FLAG_trace) { |
| 290 __ CallRuntime(Runtime::kTraceEnter, 0); | 288 __ CallRuntime(Runtime::kTraceEnter, 0); |
| 291 } | 289 } |
| 292 | 290 |
| 293 // Visit the declarations and body unless there is an illegal | 291 // Visit the declarations and body unless there is an illegal |
| 294 // redeclaration. | 292 // redeclaration. |
| 295 if (scope()->HasIllegalRedeclaration()) { | 293 if (scope()->HasIllegalRedeclaration()) { |
| 296 Comment cmnt(masm_, "[ Declarations"); | 294 Comment cmnt(masm_, "[ Declarations"); |
| 297 scope()->VisitIllegalRedeclaration(this); | 295 scope()->VisitIllegalRedeclaration(this); |
| 298 | 296 |
| 299 } else { | 297 } else { |
| 300 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); | 298 PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS); |
| 301 { Comment cmnt(masm_, "[ Declarations"); | 299 { Comment cmnt(masm_, "[ Declarations"); |
| 302 // For named function expressions, declare the function name as a | 300 // For named function expressions, declare the function name as a |
| 303 // constant. | 301 // constant. |
| 304 if (scope()->is_function_scope() && scope()->function() != NULL) { | 302 if (scope()->is_function_scope() && scope()->function() != NULL) { |
| 305 VariableDeclaration* function = scope()->function(); | 303 VariableDeclaration* function = scope()->function(); |
| 306 ASSERT(function->proxy()->var()->mode() == CONST || | 304 ASSERT(function->proxy()->var()->mode() == CONST || |
| 307 function->proxy()->var()->mode() == CONST_HARMONY); | 305 function->proxy()->var()->mode() == CONST_LEGACY); |
| 308 ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED); | 306 ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED); |
| 309 VisitVariableDeclaration(function); | 307 VisitVariableDeclaration(function); |
| 310 } | 308 } |
| 311 VisitDeclarations(scope()->declarations()); | 309 VisitDeclarations(scope()->declarations()); |
| 312 } | 310 } |
| 313 | 311 |
| 314 { Comment cmnt(masm_, "[ Stack check"); | 312 { Comment cmnt(masm_, "[ Stack check"); |
| 315 PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); | 313 PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS); |
| 316 Label ok; | 314 Label ok; |
| 317 __ LoadRoot(t0, Heap::kStackLimitRootIndex); | 315 __ LoadRoot(t0, Heap::kStackLimitRootIndex); |
| (...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 798 | 796 |
| 799 | 797 |
| 800 void FullCodeGenerator::VisitVariableDeclaration( | 798 void FullCodeGenerator::VisitVariableDeclaration( |
| 801 VariableDeclaration* declaration) { | 799 VariableDeclaration* declaration) { |
| 802 // If it was not possible to allocate the variable at compile time, we | 800 // If it was not possible to allocate the variable at compile time, we |
| 803 // need to "declare" it at runtime to make sure it actually exists in the | 801 // need to "declare" it at runtime to make sure it actually exists in the |
| 804 // local context. | 802 // local context. |
| 805 VariableProxy* proxy = declaration->proxy(); | 803 VariableProxy* proxy = declaration->proxy(); |
| 806 VariableMode mode = declaration->mode(); | 804 VariableMode mode = declaration->mode(); |
| 807 Variable* variable = proxy->var(); | 805 Variable* variable = proxy->var(); |
| 808 bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET; | 806 bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY; |
| 809 switch (variable->location()) { | 807 switch (variable->location()) { |
| 810 case Variable::UNALLOCATED: | 808 case Variable::UNALLOCATED: |
| 811 globals_->Add(variable->name(), zone()); | 809 globals_->Add(variable->name(), zone()); |
| 812 globals_->Add(variable->binding_needs_init() | 810 globals_->Add(variable->binding_needs_init() |
| 813 ? isolate()->factory()->the_hole_value() | 811 ? isolate()->factory()->the_hole_value() |
| 814 : isolate()->factory()->undefined_value(), | 812 : isolate()->factory()->undefined_value(), |
| 815 zone()); | 813 zone()); |
| 816 break; | 814 break; |
| 817 | 815 |
| 818 case Variable::PARAMETER: | 816 case Variable::PARAMETER: |
| (...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1169 __ jmp(&loop); | 1167 __ jmp(&loop); |
| 1170 | 1168 |
| 1171 __ bind(&no_descriptors); | 1169 __ bind(&no_descriptors); |
| 1172 __ Drop(1); | 1170 __ Drop(1); |
| 1173 __ jmp(&exit); | 1171 __ jmp(&exit); |
| 1174 | 1172 |
| 1175 // We got a fixed array in register v0. Iterate through that. | 1173 // We got a fixed array in register v0. Iterate through that. |
| 1176 Label non_proxy; | 1174 Label non_proxy; |
| 1177 __ bind(&fixed_array); | 1175 __ bind(&fixed_array); |
| 1178 | 1176 |
| 1179 Handle<Object> feedback = Handle<Object>( | |
| 1180 Smi::FromInt(TypeFeedbackInfo::kForInFastCaseMarker), | |
| 1181 isolate()); | |
| 1182 StoreFeedbackVectorSlot(slot, feedback); | |
| 1183 __ li(a1, FeedbackVector()); | 1177 __ li(a1, FeedbackVector()); |
| 1184 __ li(a2, Operand(Smi::FromInt(TypeFeedbackInfo::kForInSlowCaseMarker))); | 1178 __ li(a2, Operand(TypeFeedbackInfo::MegamorphicSentinel(isolate()))); |
| 1185 __ sw(a2, FieldMemOperand(a1, FixedArray::OffsetOfElementAt(slot))); | 1179 __ sw(a2, FieldMemOperand(a1, FixedArray::OffsetOfElementAt(slot))); |
| 1186 | 1180 |
| 1187 __ li(a1, Operand(Smi::FromInt(1))); // Smi indicates slow check | 1181 __ li(a1, Operand(Smi::FromInt(1))); // Smi indicates slow check |
| 1188 __ lw(a2, MemOperand(sp, 0 * kPointerSize)); // Get enumerated object | 1182 __ lw(a2, MemOperand(sp, 0 * kPointerSize)); // Get enumerated object |
| 1189 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); | 1183 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); |
| 1190 __ GetObjectType(a2, a3, a3); | 1184 __ GetObjectType(a2, a3, a3); |
| 1191 __ Branch(&non_proxy, gt, a3, Operand(LAST_JS_PROXY_TYPE)); | 1185 __ Branch(&non_proxy, gt, a3, Operand(LAST_JS_PROXY_TYPE)); |
| 1192 __ li(a1, Operand(Smi::FromInt(0))); // Zero indicates proxy | 1186 __ li(a1, Operand(Smi::FromInt(0))); // Zero indicates proxy |
| 1193 __ bind(&non_proxy); | 1187 __ bind(&non_proxy); |
| 1194 __ Push(a1, v0); // Smi and array | 1188 __ Push(a1, v0); // Smi and array |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1335 // space for nested functions that don't need literals cloning. If | 1329 // space for nested functions that don't need literals cloning. If |
| 1336 // we're running with the --always-opt or the --prepare-always-opt | 1330 // we're running with the --always-opt or the --prepare-always-opt |
| 1337 // flag, we need to use the runtime function so that the new function | 1331 // flag, we need to use the runtime function so that the new function |
| 1338 // we are creating here gets a chance to have its code optimized and | 1332 // we are creating here gets a chance to have its code optimized and |
| 1339 // doesn't just get a copy of the existing unoptimized code. | 1333 // doesn't just get a copy of the existing unoptimized code. |
| 1340 if (!FLAG_always_opt && | 1334 if (!FLAG_always_opt && |
| 1341 !FLAG_prepare_always_opt && | 1335 !FLAG_prepare_always_opt && |
| 1342 !pretenure && | 1336 !pretenure && |
| 1343 scope()->is_function_scope() && | 1337 scope()->is_function_scope() && |
| 1344 info->num_literals() == 0) { | 1338 info->num_literals() == 0) { |
| 1345 FastNewClosureStub stub(info->language_mode(), info->is_generator()); | 1339 FastNewClosureStub stub(info->strict_mode(), info->is_generator()); |
| 1346 __ li(a2, Operand(info)); | 1340 __ li(a2, Operand(info)); |
| 1347 __ CallStub(&stub); | 1341 __ CallStub(&stub); |
| 1348 } else { | 1342 } else { |
| 1349 __ li(a0, Operand(info)); | 1343 __ li(a0, Operand(info)); |
| 1350 __ LoadRoot(a1, pretenure ? Heap::kTrueValueRootIndex | 1344 __ LoadRoot(a1, pretenure ? Heap::kTrueValueRootIndex |
| 1351 : Heap::kFalseValueRootIndex); | 1345 : Heap::kFalseValueRootIndex); |
| 1352 __ Push(cp, a0, a1); | 1346 __ Push(cp, a0, a1); |
| 1353 __ CallRuntime(Runtime::kNewClosure, 3); | 1347 __ CallRuntime(Runtime::kNewClosure, 3); |
| 1354 } | 1348 } |
| 1355 context()->Plug(v0); | 1349 context()->Plug(v0); |
| 1356 } | 1350 } |
| 1357 | 1351 |
| 1358 | 1352 |
| 1359 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { | 1353 void FullCodeGenerator::VisitVariableProxy(VariableProxy* expr) { |
| 1360 Comment cmnt(masm_, "[ VariableProxy"); | 1354 Comment cmnt(masm_, "[ VariableProxy"); |
| 1361 EmitVariableLoad(expr); | 1355 EmitVariableLoad(expr); |
| 1362 } | 1356 } |
| 1363 | 1357 |
| 1364 | 1358 |
| 1365 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, | 1359 void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, |
| 1366 TypeofState typeof_state, | 1360 TypeofState typeof_state, |
| 1367 Label* slow) { | 1361 Label* slow) { |
| 1368 Register current = cp; | 1362 Register current = cp; |
| 1369 Register next = a1; | 1363 Register next = a1; |
| 1370 Register temp = a2; | 1364 Register temp = a2; |
| 1371 | 1365 |
| 1372 Scope* s = scope(); | 1366 Scope* s = scope(); |
| 1373 while (s != NULL) { | 1367 while (s != NULL) { |
| 1374 if (s->num_heap_slots() > 0) { | 1368 if (s->num_heap_slots() > 0) { |
| 1375 if (s->calls_non_strict_eval()) { | 1369 if (s->calls_sloppy_eval()) { |
| 1376 // Check that extension is NULL. | 1370 // Check that extension is NULL. |
| 1377 __ lw(temp, ContextOperand(current, Context::EXTENSION_INDEX)); | 1371 __ lw(temp, ContextOperand(current, Context::EXTENSION_INDEX)); |
| 1378 __ Branch(slow, ne, temp, Operand(zero_reg)); | 1372 __ Branch(slow, ne, temp, Operand(zero_reg)); |
| 1379 } | 1373 } |
| 1380 // Load next context in chain. | 1374 // Load next context in chain. |
| 1381 __ lw(next, ContextOperand(current, Context::PREVIOUS_INDEX)); | 1375 __ lw(next, ContextOperand(current, Context::PREVIOUS_INDEX)); |
| 1382 // Walk the rest of the chain without clobbering cp. | 1376 // Walk the rest of the chain without clobbering cp. |
| 1383 current = next; | 1377 current = next; |
| 1384 } | 1378 } |
| 1385 // If no outer scope calls eval, we do not need to check more | 1379 // If no outer scope calls eval, we do not need to check more |
| 1386 // context extensions. | 1380 // context extensions. |
| 1387 if (!s->outer_scope_calls_non_strict_eval() || s->is_eval_scope()) break; | 1381 if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope()) break; |
| 1388 s = s->outer_scope(); | 1382 s = s->outer_scope(); |
| 1389 } | 1383 } |
| 1390 | 1384 |
| 1391 if (s->is_eval_scope()) { | 1385 if (s->is_eval_scope()) { |
| 1392 Label loop, fast; | 1386 Label loop, fast; |
| 1393 if (!current.is(next)) { | 1387 if (!current.is(next)) { |
| 1394 __ Move(next, current); | 1388 __ Move(next, current); |
| 1395 } | 1389 } |
| 1396 __ bind(&loop); | 1390 __ bind(&loop); |
| 1397 // Terminate at native context. | 1391 // Terminate at native context. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1418 | 1412 |
| 1419 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, | 1413 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, |
| 1420 Label* slow) { | 1414 Label* slow) { |
| 1421 ASSERT(var->IsContextSlot()); | 1415 ASSERT(var->IsContextSlot()); |
| 1422 Register context = cp; | 1416 Register context = cp; |
| 1423 Register next = a3; | 1417 Register next = a3; |
| 1424 Register temp = t0; | 1418 Register temp = t0; |
| 1425 | 1419 |
| 1426 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { | 1420 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { |
| 1427 if (s->num_heap_slots() > 0) { | 1421 if (s->num_heap_slots() > 0) { |
| 1428 if (s->calls_non_strict_eval()) { | 1422 if (s->calls_sloppy_eval()) { |
| 1429 // Check that extension is NULL. | 1423 // Check that extension is NULL. |
| 1430 __ lw(temp, ContextOperand(context, Context::EXTENSION_INDEX)); | 1424 __ lw(temp, ContextOperand(context, Context::EXTENSION_INDEX)); |
| 1431 __ Branch(slow, ne, temp, Operand(zero_reg)); | 1425 __ Branch(slow, ne, temp, Operand(zero_reg)); |
| 1432 } | 1426 } |
| 1433 __ lw(next, ContextOperand(context, Context::PREVIOUS_INDEX)); | 1427 __ lw(next, ContextOperand(context, Context::PREVIOUS_INDEX)); |
| 1434 // Walk the rest of the chain without clobbering cp. | 1428 // Walk the rest of the chain without clobbering cp. |
| 1435 context = next; | 1429 context = next; |
| 1436 } | 1430 } |
| 1437 } | 1431 } |
| 1438 // Check that last extension is NULL. | 1432 // Check that last extension is NULL. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1454 // eval-introduced variables. Eval is used a lot without | 1448 // eval-introduced variables. Eval is used a lot without |
| 1455 // introducing variables. In those cases, we do not want to | 1449 // introducing variables. In those cases, we do not want to |
| 1456 // perform a runtime call for all variables in the scope | 1450 // perform a runtime call for all variables in the scope |
| 1457 // containing the eval. | 1451 // containing the eval. |
| 1458 if (var->mode() == DYNAMIC_GLOBAL) { | 1452 if (var->mode() == DYNAMIC_GLOBAL) { |
| 1459 EmitLoadGlobalCheckExtensions(var, typeof_state, slow); | 1453 EmitLoadGlobalCheckExtensions(var, typeof_state, slow); |
| 1460 __ Branch(done); | 1454 __ Branch(done); |
| 1461 } else if (var->mode() == DYNAMIC_LOCAL) { | 1455 } else if (var->mode() == DYNAMIC_LOCAL) { |
| 1462 Variable* local = var->local_if_not_shadowed(); | 1456 Variable* local = var->local_if_not_shadowed(); |
| 1463 __ lw(v0, ContextSlotOperandCheckExtensions(local, slow)); | 1457 __ lw(v0, ContextSlotOperandCheckExtensions(local, slow)); |
| 1464 if (local->mode() == LET || | 1458 if (local->mode() == LET || local->mode() == CONST || |
| 1465 local->mode() == CONST || | 1459 local->mode() == CONST_LEGACY) { |
| 1466 local->mode() == CONST_HARMONY) { | |
| 1467 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 1460 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 1468 __ subu(at, v0, at); // Sub as compare: at == 0 on eq. | 1461 __ subu(at, v0, at); // Sub as compare: at == 0 on eq. |
| 1469 if (local->mode() == CONST) { | 1462 if (local->mode() == CONST_LEGACY) { |
| 1470 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); | 1463 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); |
| 1471 __ Movz(v0, a0, at); // Conditional move: return Undefined if TheHole. | 1464 __ Movz(v0, a0, at); // Conditional move: return Undefined if TheHole. |
| 1472 } else { // LET || CONST_HARMONY | 1465 } else { // LET || CONST |
| 1473 __ Branch(done, ne, at, Operand(zero_reg)); | 1466 __ Branch(done, ne, at, Operand(zero_reg)); |
| 1474 __ li(a0, Operand(var->name())); | 1467 __ li(a0, Operand(var->name())); |
| 1475 __ push(a0); | 1468 __ push(a0); |
| 1476 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1469 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 1477 } | 1470 } |
| 1478 } | 1471 } |
| 1479 __ Branch(done); | 1472 __ Branch(done); |
| 1480 } | 1473 } |
| 1481 } | 1474 } |
| 1482 | 1475 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1529 // binding is initialized: | 1522 // binding is initialized: |
| 1530 // function() { f(); let x = 1; function f() { x = 2; } } | 1523 // function() { f(); let x = 1; function f() { x = 2; } } |
| 1531 // | 1524 // |
| 1532 bool skip_init_check; | 1525 bool skip_init_check; |
| 1533 if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) { | 1526 if (var->scope()->DeclarationScope() != scope()->DeclarationScope()) { |
| 1534 skip_init_check = false; | 1527 skip_init_check = false; |
| 1535 } else { | 1528 } else { |
| 1536 // Check that we always have valid source position. | 1529 // Check that we always have valid source position. |
| 1537 ASSERT(var->initializer_position() != RelocInfo::kNoPosition); | 1530 ASSERT(var->initializer_position() != RelocInfo::kNoPosition); |
| 1538 ASSERT(proxy->position() != RelocInfo::kNoPosition); | 1531 ASSERT(proxy->position() != RelocInfo::kNoPosition); |
| 1539 skip_init_check = var->mode() != CONST && | 1532 skip_init_check = var->mode() != CONST_LEGACY && |
| 1540 var->initializer_position() < proxy->position(); | 1533 var->initializer_position() < proxy->position(); |
| 1541 } | 1534 } |
| 1542 | 1535 |
| 1543 if (!skip_init_check) { | 1536 if (!skip_init_check) { |
| 1544 // Let and const need a read barrier. | 1537 // Let and const need a read barrier. |
| 1545 GetVar(v0, var); | 1538 GetVar(v0, var); |
| 1546 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 1539 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 1547 __ subu(at, v0, at); // Sub as compare: at == 0 on eq. | 1540 __ subu(at, v0, at); // Sub as compare: at == 0 on eq. |
| 1548 if (var->mode() == LET || var->mode() == CONST_HARMONY) { | 1541 if (var->mode() == LET || var->mode() == CONST) { |
| 1549 // Throw a reference error when using an uninitialized let/const | 1542 // Throw a reference error when using an uninitialized let/const |
| 1550 // binding in harmony mode. | 1543 // binding in harmony mode. |
| 1551 Label done; | 1544 Label done; |
| 1552 __ Branch(&done, ne, at, Operand(zero_reg)); | 1545 __ Branch(&done, ne, at, Operand(zero_reg)); |
| 1553 __ li(a0, Operand(var->name())); | 1546 __ li(a0, Operand(var->name())); |
| 1554 __ push(a0); | 1547 __ push(a0); |
| 1555 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 1548 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 1556 __ bind(&done); | 1549 __ bind(&done); |
| 1557 } else { | 1550 } else { |
| 1558 // Uninitalized const bindings outside of harmony mode are unholed. | 1551 // Uninitalized const bindings outside of harmony mode are unholed. |
| 1559 ASSERT(var->mode() == CONST); | 1552 ASSERT(var->mode() == CONST_LEGACY); |
| 1560 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); | 1553 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); |
| 1561 __ Movz(v0, a0, at); // Conditional move: Undefined if TheHole. | 1554 __ Movz(v0, a0, at); // Conditional move: Undefined if TheHole. |
| 1562 } | 1555 } |
| 1563 context()->Plug(v0); | 1556 context()->Plug(v0); |
| 1564 break; | 1557 break; |
| 1565 } | 1558 } |
| 1566 } | 1559 } |
| 1567 context()->Plug(var); | 1560 context()->Plug(var); |
| 1568 break; | 1561 break; |
| 1569 } | 1562 } |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1655 __ li(a2, Operand(Smi::FromInt(expr->literal_index()))); | 1648 __ li(a2, Operand(Smi::FromInt(expr->literal_index()))); |
| 1656 __ li(a1, Operand(constant_properties)); | 1649 __ li(a1, Operand(constant_properties)); |
| 1657 int flags = expr->fast_elements() | 1650 int flags = expr->fast_elements() |
| 1658 ? ObjectLiteral::kFastElements | 1651 ? ObjectLiteral::kFastElements |
| 1659 : ObjectLiteral::kNoFlags; | 1652 : ObjectLiteral::kNoFlags; |
| 1660 flags |= expr->has_function() | 1653 flags |= expr->has_function() |
| 1661 ? ObjectLiteral::kHasFunction | 1654 ? ObjectLiteral::kHasFunction |
| 1662 : ObjectLiteral::kNoFlags; | 1655 : ObjectLiteral::kNoFlags; |
| 1663 __ li(a0, Operand(Smi::FromInt(flags))); | 1656 __ li(a0, Operand(Smi::FromInt(flags))); |
| 1664 int properties_count = constant_properties->length() / 2; | 1657 int properties_count = constant_properties->length() / 2; |
| 1665 if ((FLAG_track_double_fields && expr->may_store_doubles()) || | 1658 if (expr->may_store_doubles() || expr->depth() > 1 || Serializer::enabled() || |
| 1666 expr->depth() > 1 || Serializer::enabled() || | |
| 1667 flags != ObjectLiteral::kFastElements || | 1659 flags != ObjectLiteral::kFastElements || |
| 1668 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { | 1660 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { |
| 1669 __ Push(a3, a2, a1, a0); | 1661 __ Push(a3, a2, a1, a0); |
| 1670 __ CallRuntime(Runtime::kCreateObjectLiteral, 4); | 1662 __ CallRuntime(Runtime::kCreateObjectLiteral, 4); |
| 1671 } else { | 1663 } else { |
| 1672 FastCloneShallowObjectStub stub(properties_count); | 1664 FastCloneShallowObjectStub stub(properties_count); |
| 1673 __ CallStub(&stub); | 1665 __ CallStub(&stub); |
| 1674 } | 1666 } |
| 1675 | 1667 |
| 1676 // If result_saved is true the result is on top of the stack. If | 1668 // If result_saved is true the result is on top of the stack. If |
| (...skipping 782 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2459 __ li(a2, Operand(prop->key()->AsLiteral()->value())); | 2451 __ li(a2, Operand(prop->key()->AsLiteral()->value())); |
| 2460 CallStoreIC(); | 2452 CallStoreIC(); |
| 2461 break; | 2453 break; |
| 2462 } | 2454 } |
| 2463 case KEYED_PROPERTY: { | 2455 case KEYED_PROPERTY: { |
| 2464 __ push(result_register()); // Preserve value. | 2456 __ push(result_register()); // Preserve value. |
| 2465 VisitForStackValue(prop->obj()); | 2457 VisitForStackValue(prop->obj()); |
| 2466 VisitForAccumulatorValue(prop->key()); | 2458 VisitForAccumulatorValue(prop->key()); |
| 2467 __ mov(a1, result_register()); | 2459 __ mov(a1, result_register()); |
| 2468 __ Pop(a0, a2); // a0 = restored value. | 2460 __ Pop(a0, a2); // a0 = restored value. |
| 2469 Handle<Code> ic = is_classic_mode() | 2461 Handle<Code> ic = strict_mode() == SLOPPY |
| 2470 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2462 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2471 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2463 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2472 CallIC(ic); | 2464 CallIC(ic); |
| 2473 break; | 2465 break; |
| 2474 } | 2466 } |
| 2475 } | 2467 } |
| 2476 context()->Plug(v0); | 2468 context()->Plug(v0); |
| 2477 } | 2469 } |
| 2478 | 2470 |
| 2479 | 2471 |
| 2480 void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( | 2472 void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( |
| 2481 Variable* var, MemOperand location) { | 2473 Variable* var, MemOperand location) { |
| 2482 __ sw(result_register(), location); | 2474 __ sw(result_register(), location); |
| 2483 if (var->IsContextSlot()) { | 2475 if (var->IsContextSlot()) { |
| 2484 // RecordWrite may destroy all its register arguments. | 2476 // RecordWrite may destroy all its register arguments. |
| 2485 __ Move(a3, result_register()); | 2477 __ Move(a3, result_register()); |
| 2486 int offset = Context::SlotOffset(var->index()); | 2478 int offset = Context::SlotOffset(var->index()); |
| 2487 __ RecordWriteContextSlot( | 2479 __ RecordWriteContextSlot( |
| 2488 a1, offset, a3, a2, kRAHasBeenSaved, kDontSaveFPRegs); | 2480 a1, offset, a3, a2, kRAHasBeenSaved, kDontSaveFPRegs); |
| 2489 } | 2481 } |
| 2490 } | 2482 } |
| 2491 | 2483 |
| 2492 | 2484 |
| 2493 void FullCodeGenerator::EmitCallStoreContextSlot( | 2485 void FullCodeGenerator::EmitCallStoreContextSlot( |
| 2494 Handle<String> name, LanguageMode mode) { | 2486 Handle<String> name, StrictMode strict_mode) { |
| 2495 __ li(a1, Operand(name)); | 2487 __ li(a1, Operand(name)); |
| 2496 __ li(a0, Operand(Smi::FromInt(mode))); | 2488 __ li(a0, Operand(Smi::FromInt(strict_mode))); |
| 2497 __ Push(v0, cp, a1, a0); // Value, context, name, strict mode. | 2489 __ Push(v0, cp, a1, a0); // Value, context, name, strict mode. |
| 2498 __ CallRuntime(Runtime::kStoreContextSlot, 4); | 2490 __ CallRuntime(Runtime::kStoreContextSlot, 4); |
| 2499 } | 2491 } |
| 2500 | 2492 |
| 2501 | 2493 |
| 2502 void FullCodeGenerator::EmitVariableAssignment(Variable* var, | 2494 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) { |
| 2503 Token::Value op) { | |
| 2504 if (var->IsUnallocated()) { | 2495 if (var->IsUnallocated()) { |
| 2505 // Global var, const, or let. | 2496 // Global var, const, or let. |
| 2506 __ mov(a0, result_register()); | 2497 __ mov(a0, result_register()); |
| 2507 __ li(a2, Operand(var->name())); | 2498 __ li(a2, Operand(var->name())); |
| 2508 __ lw(a1, GlobalObjectOperand()); | 2499 __ lw(a1, GlobalObjectOperand()); |
| 2509 CallStoreIC(); | 2500 CallStoreIC(); |
| 2510 | 2501 |
| 2511 } else if (op == Token::INIT_CONST) { | 2502 } else if (op == Token::INIT_CONST_LEGACY) { |
| 2512 // Const initializers need a write barrier. | 2503 // Const initializers need a write barrier. |
| 2513 ASSERT(!var->IsParameter()); // No const parameters. | 2504 ASSERT(!var->IsParameter()); // No const parameters. |
| 2514 if (var->IsLookupSlot()) { | 2505 if (var->IsLookupSlot()) { |
| 2515 __ li(a0, Operand(var->name())); | 2506 __ li(a0, Operand(var->name())); |
| 2516 __ Push(v0, cp, a0); // Context and name. | 2507 __ Push(v0, cp, a0); // Context and name. |
| 2517 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); | 2508 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); |
| 2518 } else { | 2509 } else { |
| 2519 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 2510 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); |
| 2520 Label skip; | 2511 Label skip; |
| 2521 MemOperand location = VarOperand(var, a1); | 2512 MemOperand location = VarOperand(var, a1); |
| 2522 __ lw(a2, location); | 2513 __ lw(a2, location); |
| 2523 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 2514 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 2524 __ Branch(&skip, ne, a2, Operand(at)); | 2515 __ Branch(&skip, ne, a2, Operand(at)); |
| 2525 EmitStoreToStackLocalOrContextSlot(var, location); | 2516 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2526 __ bind(&skip); | 2517 __ bind(&skip); |
| 2527 } | 2518 } |
| 2528 | 2519 |
| 2529 } else if (var->mode() == LET && op != Token::INIT_LET) { | 2520 } else if (var->mode() == LET && op != Token::INIT_LET) { |
| 2530 // Non-initializing assignment to let variable needs a write barrier. | 2521 // Non-initializing assignment to let variable needs a write barrier. |
| 2531 if (var->IsLookupSlot()) { | 2522 if (var->IsLookupSlot()) { |
| 2532 EmitCallStoreContextSlot(var->name(), language_mode()); | 2523 EmitCallStoreContextSlot(var->name(), strict_mode()); |
| 2533 } else { | 2524 } else { |
| 2534 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); | 2525 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); |
| 2535 Label assign; | 2526 Label assign; |
| 2536 MemOperand location = VarOperand(var, a1); | 2527 MemOperand location = VarOperand(var, a1); |
| 2537 __ lw(a3, location); | 2528 __ lw(a3, location); |
| 2538 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); | 2529 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); |
| 2539 __ Branch(&assign, ne, a3, Operand(t0)); | 2530 __ Branch(&assign, ne, a3, Operand(t0)); |
| 2540 __ li(a3, Operand(var->name())); | 2531 __ li(a3, Operand(var->name())); |
| 2541 __ push(a3); | 2532 __ push(a3); |
| 2542 __ CallRuntime(Runtime::kThrowReferenceError, 1); | 2533 __ CallRuntime(Runtime::kThrowReferenceError, 1); |
| 2543 // Perform the assignment. | 2534 // Perform the assignment. |
| 2544 __ bind(&assign); | 2535 __ bind(&assign); |
| 2545 EmitStoreToStackLocalOrContextSlot(var, location); | 2536 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2546 } | 2537 } |
| 2547 | 2538 |
| 2548 } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) { | 2539 } else if (!var->is_const_mode() || op == Token::INIT_CONST) { |
| 2549 // Assignment to var or initializing assignment to let/const | 2540 // Assignment to var or initializing assignment to let/const |
| 2550 // in harmony mode. | 2541 // in harmony mode. |
| 2551 if (var->IsLookupSlot()) { | 2542 if (var->IsLookupSlot()) { |
| 2552 EmitCallStoreContextSlot(var->name(), language_mode()); | 2543 EmitCallStoreContextSlot(var->name(), strict_mode()); |
| 2553 } else { | 2544 } else { |
| 2554 ASSERT((var->IsStackAllocated() || var->IsContextSlot())); | 2545 ASSERT((var->IsStackAllocated() || var->IsContextSlot())); |
| 2555 MemOperand location = VarOperand(var, a1); | 2546 MemOperand location = VarOperand(var, a1); |
| 2556 if (generate_debug_code_ && op == Token::INIT_LET) { | 2547 if (generate_debug_code_ && op == Token::INIT_LET) { |
| 2557 // Check for an uninitialized let binding. | 2548 // Check for an uninitialized let binding. |
| 2558 __ lw(a2, location); | 2549 __ lw(a2, location); |
| 2559 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); | 2550 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); |
| 2560 __ Check(eq, kLetBindingReInitialization, a2, Operand(t0)); | 2551 __ Check(eq, kLetBindingReInitialization, a2, Operand(t0)); |
| 2561 } | 2552 } |
| 2562 EmitStoreToStackLocalOrContextSlot(var, location); | 2553 EmitStoreToStackLocalOrContextSlot(var, location); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 2591 // Record source code position before IC call. | 2582 // Record source code position before IC call. |
| 2592 SetSourcePosition(expr->position()); | 2583 SetSourcePosition(expr->position()); |
| 2593 // Call keyed store IC. | 2584 // Call keyed store IC. |
| 2594 // The arguments are: | 2585 // The arguments are: |
| 2595 // - a0 is the value, | 2586 // - a0 is the value, |
| 2596 // - a1 is the key, | 2587 // - a1 is the key, |
| 2597 // - a2 is the receiver. | 2588 // - a2 is the receiver. |
| 2598 __ mov(a0, result_register()); | 2589 __ mov(a0, result_register()); |
| 2599 __ Pop(a2, a1); // a1 = key. | 2590 __ Pop(a2, a1); // a1 = key. |
| 2600 | 2591 |
| 2601 Handle<Code> ic = is_classic_mode() | 2592 Handle<Code> ic = strict_mode() == SLOPPY |
| 2602 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2593 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2603 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2594 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2604 CallIC(ic, expr->AssignmentFeedbackId()); | 2595 CallIC(ic, expr->AssignmentFeedbackId()); |
| 2605 | 2596 |
| 2606 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2597 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2607 context()->Plug(v0); | 2598 context()->Plug(v0); |
| 2608 } | 2599 } |
| 2609 | 2600 |
| 2610 | 2601 |
| 2611 void FullCodeGenerator::VisitProperty(Property* expr) { | 2602 void FullCodeGenerator::VisitProperty(Property* expr) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2641 int arg_count = args->length(); | 2632 int arg_count = args->length(); |
| 2642 | 2633 |
| 2643 CallFunctionFlags flags; | 2634 CallFunctionFlags flags; |
| 2644 // Get the target function. | 2635 // Get the target function. |
| 2645 if (callee->IsVariableProxy()) { | 2636 if (callee->IsVariableProxy()) { |
| 2646 { StackValueContext context(this); | 2637 { StackValueContext context(this); |
| 2647 EmitVariableLoad(callee->AsVariableProxy()); | 2638 EmitVariableLoad(callee->AsVariableProxy()); |
| 2648 PrepareForBailout(callee, NO_REGISTERS); | 2639 PrepareForBailout(callee, NO_REGISTERS); |
| 2649 } | 2640 } |
| 2650 // Push undefined as receiver. This is patched in the method prologue if it | 2641 // Push undefined as receiver. This is patched in the method prologue if it |
| 2651 // is a classic mode method. | 2642 // is a sloppy mode method. |
| 2652 __ Push(isolate()->factory()->undefined_value()); | 2643 __ Push(isolate()->factory()->undefined_value()); |
| 2653 flags = NO_CALL_FUNCTION_FLAGS; | 2644 flags = NO_CALL_FUNCTION_FLAGS; |
| 2654 } else { | 2645 } else { |
| 2655 // Load the function from the receiver. | 2646 // Load the function from the receiver. |
| 2656 ASSERT(callee->IsProperty()); | 2647 ASSERT(callee->IsProperty()); |
| 2657 __ lw(v0, MemOperand(sp, 0)); | 2648 __ lw(v0, MemOperand(sp, 0)); |
| 2658 EmitNamedPropertyLoad(callee->AsProperty()); | 2649 EmitNamedPropertyLoad(callee->AsProperty()); |
| 2659 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2650 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
| 2660 // Push the target function under the receiver. | 2651 // Push the target function under the receiver. |
| 2661 __ lw(at, MemOperand(sp, 0)); | 2652 __ lw(at, MemOperand(sp, 0)); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2731 ZoneList<Expression*>* args = expr->arguments(); | 2722 ZoneList<Expression*>* args = expr->arguments(); |
| 2732 int arg_count = args->length(); | 2723 int arg_count = args->length(); |
| 2733 { PreservePositionScope scope(masm()->positions_recorder()); | 2724 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2734 for (int i = 0; i < arg_count; i++) { | 2725 for (int i = 0; i < arg_count; i++) { |
| 2735 VisitForStackValue(args->at(i)); | 2726 VisitForStackValue(args->at(i)); |
| 2736 } | 2727 } |
| 2737 } | 2728 } |
| 2738 // Record source position for debugger. | 2729 // Record source position for debugger. |
| 2739 SetSourcePosition(expr->position()); | 2730 SetSourcePosition(expr->position()); |
| 2740 | 2731 |
| 2741 Handle<Object> uninitialized = | |
| 2742 TypeFeedbackInfo::UninitializedSentinel(isolate()); | |
| 2743 StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized); | |
| 2744 __ li(a2, FeedbackVector()); | 2732 __ li(a2, FeedbackVector()); |
| 2745 __ li(a3, Operand(Smi::FromInt(expr->CallFeedbackSlot()))); | 2733 __ li(a3, Operand(Smi::FromInt(expr->CallFeedbackSlot()))); |
| 2746 | 2734 |
| 2747 // Record call targets in unoptimized code. | 2735 // Record call targets in unoptimized code. |
| 2748 CallFunctionStub stub(arg_count, RECORD_CALL_TARGET); | 2736 CallFunctionStub stub(arg_count, RECORD_CALL_TARGET); |
| 2749 __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 2737 __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
| 2750 __ CallStub(&stub); | 2738 __ CallStub(&stub); |
| 2751 RecordJSReturnSite(expr); | 2739 RecordJSReturnSite(expr); |
| 2752 // Restore context register. | 2740 // Restore context register. |
| 2753 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2741 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2754 context()->DropAndPlug(1, v0); | 2742 context()->DropAndPlug(1, v0); |
| 2755 } | 2743 } |
| 2756 | 2744 |
| 2757 | 2745 |
| 2758 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { | 2746 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { |
| 2759 // t2: copy of the first argument or undefined if it doesn't exist. | 2747 // t2: copy of the first argument or undefined if it doesn't exist. |
| 2760 if (arg_count > 0) { | 2748 if (arg_count > 0) { |
| 2761 __ lw(t2, MemOperand(sp, arg_count * kPointerSize)); | 2749 __ lw(t2, MemOperand(sp, arg_count * kPointerSize)); |
| 2762 } else { | 2750 } else { |
| 2763 __ LoadRoot(t2, Heap::kUndefinedValueRootIndex); | 2751 __ LoadRoot(t2, Heap::kUndefinedValueRootIndex); |
| 2764 } | 2752 } |
| 2765 | 2753 |
| 2766 // t1: the receiver of the enclosing function. | 2754 // t1: the receiver of the enclosing function. |
| 2767 int receiver_offset = 2 + info_->scope()->num_parameters(); | 2755 int receiver_offset = 2 + info_->scope()->num_parameters(); |
| 2768 __ lw(t1, MemOperand(fp, receiver_offset * kPointerSize)); | 2756 __ lw(t1, MemOperand(fp, receiver_offset * kPointerSize)); |
| 2769 | 2757 |
| 2770 // t0: the language mode. | 2758 // t0: the strict mode. |
| 2771 __ li(t0, Operand(Smi::FromInt(language_mode()))); | 2759 __ li(t0, Operand(Smi::FromInt(strict_mode()))); |
| 2772 | 2760 |
| 2773 // a1: the start position of the scope the calls resides in. | 2761 // a1: the start position of the scope the calls resides in. |
| 2774 __ li(a1, Operand(Smi::FromInt(scope()->start_position()))); | 2762 __ li(a1, Operand(Smi::FromInt(scope()->start_position()))); |
| 2775 | 2763 |
| 2776 // Do the runtime call. | 2764 // Do the runtime call. |
| 2777 __ Push(t2, t1, t0, a1); | 2765 __ Push(t2, t1, t0, a1); |
| 2778 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); | 2766 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); |
| 2779 } | 2767 } |
| 2780 | 2768 |
| 2781 | 2769 |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2918 | 2906 |
| 2919 // Call the construct call builtin that handles allocation and | 2907 // Call the construct call builtin that handles allocation and |
| 2920 // constructor invocation. | 2908 // constructor invocation. |
| 2921 SetSourcePosition(expr->position()); | 2909 SetSourcePosition(expr->position()); |
| 2922 | 2910 |
| 2923 // Load function and argument count into a1 and a0. | 2911 // Load function and argument count into a1 and a0. |
| 2924 __ li(a0, Operand(arg_count)); | 2912 __ li(a0, Operand(arg_count)); |
| 2925 __ lw(a1, MemOperand(sp, arg_count * kPointerSize)); | 2913 __ lw(a1, MemOperand(sp, arg_count * kPointerSize)); |
| 2926 | 2914 |
| 2927 // Record call targets in unoptimized code. | 2915 // Record call targets in unoptimized code. |
| 2928 Handle<Object> uninitialized = | |
| 2929 TypeFeedbackInfo::UninitializedSentinel(isolate()); | |
| 2930 StoreFeedbackVectorSlot(expr->CallNewFeedbackSlot(), uninitialized); | |
| 2931 __ li(a2, FeedbackVector()); | 2916 __ li(a2, FeedbackVector()); |
| 2932 __ li(a3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot()))); | 2917 __ li(a3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot()))); |
| 2933 | 2918 |
| 2934 CallConstructStub stub(RECORD_CALL_TARGET); | 2919 CallConstructStub stub(RECORD_CALL_TARGET); |
| 2935 __ Call(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL); | 2920 __ Call(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL); |
| 2936 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); | 2921 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); |
| 2937 context()->Plug(v0); | 2922 context()->Plug(v0); |
| 2938 } | 2923 } |
| 2939 | 2924 |
| 2940 | 2925 |
| (...skipping 1292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4233 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 4218 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
| 4234 switch (expr->op()) { | 4219 switch (expr->op()) { |
| 4235 case Token::DELETE: { | 4220 case Token::DELETE: { |
| 4236 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); | 4221 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); |
| 4237 Property* property = expr->expression()->AsProperty(); | 4222 Property* property = expr->expression()->AsProperty(); |
| 4238 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 4223 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 4239 | 4224 |
| 4240 if (property != NULL) { | 4225 if (property != NULL) { |
| 4241 VisitForStackValue(property->obj()); | 4226 VisitForStackValue(property->obj()); |
| 4242 VisitForStackValue(property->key()); | 4227 VisitForStackValue(property->key()); |
| 4243 StrictModeFlag strict_mode_flag = (language_mode() == CLASSIC_MODE) | 4228 __ li(a1, Operand(Smi::FromInt(strict_mode()))); |
| 4244 ? kNonStrictMode : kStrictMode; | |
| 4245 __ li(a1, Operand(Smi::FromInt(strict_mode_flag))); | |
| 4246 __ push(a1); | 4229 __ push(a1); |
| 4247 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4230 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
| 4248 context()->Plug(v0); | 4231 context()->Plug(v0); |
| 4249 } else if (proxy != NULL) { | 4232 } else if (proxy != NULL) { |
| 4250 Variable* var = proxy->var(); | 4233 Variable* var = proxy->var(); |
| 4251 // Delete of an unqualified identifier is disallowed in strict mode | 4234 // Delete of an unqualified identifier is disallowed in strict mode |
| 4252 // but "delete this" is allowed. | 4235 // but "delete this" is allowed. |
| 4253 ASSERT(language_mode() == CLASSIC_MODE || var->is_this()); | 4236 ASSERT(strict_mode() == SLOPPY || var->is_this()); |
| 4254 if (var->IsUnallocated()) { | 4237 if (var->IsUnallocated()) { |
| 4255 __ lw(a2, GlobalObjectOperand()); | 4238 __ lw(a2, GlobalObjectOperand()); |
| 4256 __ li(a1, Operand(var->name())); | 4239 __ li(a1, Operand(var->name())); |
| 4257 __ li(a0, Operand(Smi::FromInt(kNonStrictMode))); | 4240 __ li(a0, Operand(Smi::FromInt(SLOPPY))); |
| 4258 __ Push(a2, a1, a0); | 4241 __ Push(a2, a1, a0); |
| 4259 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4242 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
| 4260 context()->Plug(v0); | 4243 context()->Plug(v0); |
| 4261 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4244 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
| 4262 // Result of deleting non-global, non-dynamic variables is false. | 4245 // Result of deleting non-global, non-dynamic variables is false. |
| 4263 // The subexpression does not have side effects. | 4246 // The subexpression does not have side effects. |
| 4264 context()->Plug(var->is_this()); | 4247 context()->Plug(var->is_this()); |
| 4265 } else { | 4248 } else { |
| 4266 // Non-global variable. Call the runtime to try to delete from the | 4249 // Non-global variable. Call the runtime to try to delete from the |
| 4267 // context where the variable was introduced. | 4250 // context where the variable was introduced. |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4506 context()->PlugTOS(); | 4489 context()->PlugTOS(); |
| 4507 } | 4490 } |
| 4508 } else { | 4491 } else { |
| 4509 context()->Plug(v0); | 4492 context()->Plug(v0); |
| 4510 } | 4493 } |
| 4511 break; | 4494 break; |
| 4512 } | 4495 } |
| 4513 case KEYED_PROPERTY: { | 4496 case KEYED_PROPERTY: { |
| 4514 __ mov(a0, result_register()); // Value. | 4497 __ mov(a0, result_register()); // Value. |
| 4515 __ Pop(a2, a1); // a1 = key, a2 = receiver. | 4498 __ Pop(a2, a1); // a1 = key, a2 = receiver. |
| 4516 Handle<Code> ic = is_classic_mode() | 4499 Handle<Code> ic = strict_mode() == SLOPPY |
| 4517 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 4500 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 4518 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 4501 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 4519 CallIC(ic, expr->CountStoreFeedbackId()); | 4502 CallIC(ic, expr->CountStoreFeedbackId()); |
| 4520 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4503 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4521 if (expr->is_postfix()) { | 4504 if (expr->is_postfix()) { |
| 4522 if (!context()->IsEffect()) { | 4505 if (!context()->IsEffect()) { |
| 4523 context()->PlugTOS(); | 4506 context()->PlugTOS(); |
| 4524 } | 4507 } |
| 4525 } else { | 4508 } else { |
| 4526 context()->Plug(v0); | 4509 context()->Plug(v0); |
| (...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4967 Assembler::target_address_at(pc_immediate_load_address)) == | 4950 Assembler::target_address_at(pc_immediate_load_address)) == |
| 4968 reinterpret_cast<uint32_t>( | 4951 reinterpret_cast<uint32_t>( |
| 4969 isolate->builtins()->OsrAfterStackCheck()->entry())); | 4952 isolate->builtins()->OsrAfterStackCheck()->entry())); |
| 4970 return OSR_AFTER_STACK_CHECK; | 4953 return OSR_AFTER_STACK_CHECK; |
| 4971 } | 4954 } |
| 4972 | 4955 |
| 4973 | 4956 |
| 4974 } } // namespace v8::internal | 4957 } } // namespace v8::internal |
| 4975 | 4958 |
| 4976 #endif // V8_TARGET_ARCH_MIPS | 4959 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |