OLD | NEW |
---|---|
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 1477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1488 // frame. | 1488 // frame. |
1489 frame_->PushElementAt(target.size() - 1); | 1489 frame_->PushElementAt(target.size() - 1); |
1490 // Result ignored = frame_->CallRuntime(Runtime::kToSlowProperties, 1); | 1490 // Result ignored = frame_->CallRuntime(Runtime::kToSlowProperties, 1); |
1491 } | 1491 } |
1492 if (node->op() == Token::ASSIGN || | 1492 if (node->op() == Token::ASSIGN || |
1493 node->op() == Token::INIT_VAR || | 1493 node->op() == Token::INIT_VAR || |
1494 node->op() == Token::INIT_CONST) { | 1494 node->op() == Token::INIT_CONST) { |
1495 Load(node->value()); | 1495 Load(node->value()); |
1496 | 1496 |
1497 } else { | 1497 } else { |
1498 // TODO(X64): Make compound assignments work. | |
1499 /* | |
1500 Literal* literal = node->value()->AsLiteral(); | 1498 Literal* literal = node->value()->AsLiteral(); |
1501 bool overwrite_value = | 1499 bool overwrite_value = |
1502 (node->value()->AsBinaryOperation() != NULL && | 1500 (node->value()->AsBinaryOperation() != NULL && |
1503 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); | 1501 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); |
1504 Variable* right_var = node->value()->AsVariableProxy()->AsVariable(); | 1502 Variable* right_var = node->value()->AsVariableProxy()->AsVariable(); |
1505 // There are two cases where the target is not read in the right hand | 1503 // There are two cases where the target is not read in the right hand |
1506 // side, that are easy to test for: the right hand side is a literal, | 1504 // side, that are easy to test for: the right hand side is a literal, |
1507 // or the right hand side is a different variable. TakeValue invalidates | 1505 // or the right hand side is a different variable. TakeValue invalidates |
1508 // the target, with an implicit promise that it will be written to again | 1506 // the target, with an implicit promise that it will be written to again |
1509 // before it is read. | 1507 // before it is read. |
1510 if (literal != NULL || (right_var != NULL && right_var != var)) { | 1508 // TODO(X64): Implement TakeValue optimization. |
1511 target.TakeValue(NOT_INSIDE_TYPEOF); | 1509 if (false && literal != NULL || (right_var != NULL && right_var != var)) { |
1510 // target.TakeValue(NOT_INSIDE_TYPEOF); | |
1512 } else { | 1511 } else { |
1513 target.GetValue(NOT_INSIDE_TYPEOF); | 1512 target.GetValue(NOT_INSIDE_TYPEOF); |
1514 } | 1513 } |
1515 */ | |
1516 Load(node->value()); | 1514 Load(node->value()); |
1517 /* | |
1518 GenericBinaryOperation(node->binary_op(), | 1515 GenericBinaryOperation(node->binary_op(), |
1519 node->type(), | 1516 node->type(), |
1520 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); | 1517 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); |
1521 */ | |
1522 } | 1518 } |
1523 | 1519 |
1524 if (var != NULL && | 1520 if (var != NULL && |
1525 var->mode() == Variable::CONST && | 1521 var->mode() == Variable::CONST && |
1526 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) { | 1522 node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) { |
1527 // Assignment ignored - leave the value on the stack. | 1523 // Assignment ignored - leave the value on the stack. |
1528 } else { | 1524 } else { |
1529 CodeForSourcePosition(node->position()); | 1525 CodeForSourcePosition(node->position()); |
1530 if (node->op() == Token::INIT_CONST) { | 1526 if (node->op() == Token::INIT_CONST) { |
1531 // Dynamic constant initializations must use the function context | 1527 // Dynamic constant initializations must use the function context |
(...skipping 736 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2268 Comparison(cc, strict, destination()); | 2264 Comparison(cc, strict, destination()); |
2269 } | 2265 } |
2270 | 2266 |
2271 | 2267 |
2272 void CodeGenerator::VisitThisFunction(ThisFunction* node) { | 2268 void CodeGenerator::VisitThisFunction(ThisFunction* node) { |
2273 frame_->PushFunction(); | 2269 frame_->PushFunction(); |
2274 } | 2270 } |
2275 | 2271 |
2276 | 2272 |
2277 void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { | 2273 void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* args) { |
2278 UNIMPLEMENTED(); | 2274 ASSERT(args->length() == 1); |
2275 | |
2276 // ArgumentsAccessStub expects the key in edx and the formal | |
2277 // parameter count in eax. | |
Lasse Reichstein
2009/06/25 11:54:59
rdx * 2
| |
2278 Load(args->at(0)); | |
2279 Result key = frame_->Pop(); | |
2280 // Explicitly create a constant result. | |
2281 Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters()))); | |
2282 // Call the shared stub to get to arguments[key]. | |
2283 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); | |
2284 Result result = frame_->CallStub(&stub, &key, &count); | |
2285 frame_->Push(&result); | |
2279 } | 2286 } |
2280 | 2287 |
2288 | |
2289 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { | |
2290 ASSERT(args->length() == 1); | |
2291 Load(args->at(0)); | |
2292 Result value = frame_->Pop(); | |
2293 value.ToRegister(); | |
2294 ASSERT(value.is_valid()); | |
2295 __ testl(value.reg(), Immediate(kSmiTagMask)); | |
2296 destination()->false_target()->Branch(equal); | |
2297 // It is a heap object - get map. | |
2298 // Check if the object is a JS array or not. | |
2299 __ CmpObjectType(value.reg(), JS_ARRAY_TYPE, kScratchRegister); | |
2300 value.Unuse(); | |
2301 destination()->Split(equal); | |
2302 } | |
2303 | |
2304 | |
2281 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { | 2305 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { |
2282 UNIMPLEMENTED();} | 2306 ASSERT(args->length() == 0); |
2307 // ArgumentsAccessStub takes the parameter count as an input argument | |
2308 // in register eax. Create a constant result for it. | |
Lasse Reichstein
2009/06/25 11:54:59
rax
| |
2309 Result count(Handle<Smi>(Smi::FromInt(scope_->num_parameters()))); | |
2310 // Call the shared stub to get to the arguments.length. | |
2311 ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH); | |
2312 Result result = frame_->CallStub(&stub, &count); | |
2313 frame_->Push(&result); | |
2314 } | |
2315 | |
2283 | 2316 |
2284 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* a) { | 2317 void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* a) { |
2285 UNIMPLEMENTED(); | 2318 UNIMPLEMENTED(); |
2286 } | 2319 } |
2287 | 2320 |
2288 void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { | |
2289 UNIMPLEMENTED(); | |
2290 } | |
2291 | 2321 |
2292 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { | 2322 void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { |
2293 UNIMPLEMENTED(); | 2323 UNIMPLEMENTED(); |
2294 } | 2324 } |
2295 | 2325 |
2326 | |
2296 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { | 2327 void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { |
2297 UNIMPLEMENTED(); | 2328 ASSERT(args->length() == 1); |
2329 Load(args->at(0)); | |
2330 Result value = frame_->Pop(); | |
2331 value.ToRegister(); | |
2332 ASSERT(value.is_valid()); | |
2333 __ testl(value.reg(), Immediate(kSmiTagMask)); | |
2334 value.Unuse(); | |
2335 destination()->Split(zero); | |
2298 } | 2336 } |
2299 | 2337 |
2338 | |
2300 void CodeGenerator::GenerateLog(ZoneList<Expression*>* a) { | 2339 void CodeGenerator::GenerateLog(ZoneList<Expression*>* a) { |
2301 UNIMPLEMENTED(); | 2340 UNIMPLEMENTED(); |
2302 } | 2341 } |
2303 | 2342 |
2304 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { | 2343 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { |
2305 UNIMPLEMENTED(); | 2344 ASSERT(args->length() == 2); |
2345 | |
2346 // Load the two objects into registers and perform the comparison. | |
2347 Load(args->at(0)); | |
2348 Load(args->at(1)); | |
2349 Result right = frame_->Pop(); | |
2350 Result left = frame_->Pop(); | |
2351 right.ToRegister(); | |
2352 left.ToRegister(); | |
2353 __ cmpq(right.reg(), left.reg()); | |
2354 right.Unuse(); | |
2355 left.Unuse(); | |
2356 destination()->Split(equal); | |
2306 } | 2357 } |
2307 | 2358 |
2359 | |
2360 | |
2308 void CodeGenerator::GenerateRandomPositiveSmi(ZoneList<Expression*>* a) { | 2361 void CodeGenerator::GenerateRandomPositiveSmi(ZoneList<Expression*>* a) { |
2309 UNIMPLEMENTED(); | 2362 UNIMPLEMENTED(); |
2310 } | 2363 } |
2311 | 2364 |
2312 void CodeGenerator::GenerateFastMathOp(MathOp op, ZoneList<Expression*>* args) { | 2365 void CodeGenerator::GenerateFastMathOp(MathOp op, ZoneList<Expression*>* args) { |
2313 UNIMPLEMENTED(); | 2366 UNIMPLEMENTED(); |
2314 } | 2367 } |
2315 | 2368 |
2369 | |
2316 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) { | 2370 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) { |
2317 UNIMPLEMENTED(); | 2371 ASSERT(args->length() == 2); |
2372 JumpTarget leave; | |
2373 Load(args->at(0)); // Load the object. | |
2374 Load(args->at(1)); // Load the value. | |
2375 Result value = frame_->Pop(); | |
2376 Result object = frame_->Pop(); | |
2377 value.ToRegister(); | |
2378 object.ToRegister(); | |
2379 | |
2380 // if (object->IsSmi()) return value. | |
2381 __ testl(object.reg(), Immediate(kSmiTagMask)); | |
2382 leave.Branch(zero, &value); | |
2383 | |
2384 // It is a heap object - get its map. | |
2385 Result scratch = allocator_->Allocate(); | |
2386 ASSERT(scratch.is_valid()); | |
2387 // if (!object->IsJSValue()) return value. | |
2388 __ CmpObjectType(object.reg(), JS_VALUE_TYPE, scratch.reg()); | |
2389 leave.Branch(not_equal, &value); | |
2390 | |
2391 // Store the value. | |
2392 __ movq(FieldOperand(object.reg(), JSValue::kValueOffset), value.reg()); | |
2393 // Update the write barrier. Save the value as it will be | |
2394 // overwritten by the write barrier code and is needed afterward. | |
2395 Result duplicate_value = allocator_->Allocate(); | |
2396 ASSERT(duplicate_value.is_valid()); | |
2397 __ movq(duplicate_value.reg(), value.reg()); | |
2398 // The object register is also overwritten by the write barrier and | |
2399 // possibly aliased in the frame. | |
2400 frame_->Spill(object.reg()); | |
2401 __ RecordWrite(object.reg(), JSValue::kValueOffset, duplicate_value.reg(), | |
2402 scratch.reg()); | |
2403 object.Unuse(); | |
2404 scratch.Unuse(); | |
2405 duplicate_value.Unuse(); | |
2406 | |
2407 // Leave. | |
2408 leave.Bind(&value); | |
2409 frame_->Push(&value); | |
2318 } | 2410 } |
2319 | 2411 |
2412 | |
2320 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { | 2413 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { |
2321 UNIMPLEMENTED(); | 2414 UNIMPLEMENTED(); |
2322 } | 2415 } |
2323 | 2416 |
2324 // ----------------------------------------------------------------------------- | 2417 // ----------------------------------------------------------------------------- |
2325 // CodeGenerator implementation of Expressions | 2418 // CodeGenerator implementation of Expressions |
2326 | 2419 |
2327 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { | 2420 void CodeGenerator::Load(Expression* x, TypeofState typeof_state) { |
2328 #ifdef DEBUG | 2421 #ifdef DEBUG |
2329 int original_height = frame_->height(); | 2422 int original_height = frame_->height(); |
(...skipping 3173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5503 break; | 5596 break; |
5504 default: | 5597 default: |
5505 UNREACHABLE(); | 5598 UNREACHABLE(); |
5506 } | 5599 } |
5507 } | 5600 } |
5508 | 5601 |
5509 | 5602 |
5510 #undef __ | 5603 #undef __ |
5511 | 5604 |
5512 } } // namespace v8::internal | 5605 } } // namespace v8::internal |
OLD | NEW |