blob: 2e3025b979c19a32538ccf81296720509036e347 [file] [log] [blame]
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001// Copyright 2006-2008 Google Inc. All Rights Reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include <stdlib.h>
29
30#include "v8.h"
31
32#include "accessors.h"
33#include "api.h"
34#include "arguments.h"
35#include "compiler.h"
36#include "cpu.h"
37#include "dateparser.h"
38#include "debug.h"
39#include "execution.h"
40#include "jsregexp.h"
41#include "platform.h"
42#include "runtime.h"
43#include "scopeinfo.h"
44#include "v8threads.h"
45
46namespace v8 { namespace internal {
47
48
49#define RUNTIME_ASSERT(value) do { \
50 if (!(value)) return IllegalOperation(); \
51} while (false)
52
53// Cast the given object to a value of the specified type and store
54// it in a variable with the given name. If the object is not of the
55// expected type call IllegalOperation and return.
56#define CONVERT_CHECKED(Type, name, obj) \
57 RUNTIME_ASSERT(obj->Is##Type()); \
58 Type* name = Type::cast(obj);
59
60#define CONVERT_ARG_CHECKED(Type, name, index) \
61 RUNTIME_ASSERT(args[index]->Is##Type()); \
62 Handle<Type> name = args.at<Type>(index);
63
kasper.lundbd3ec4e2008-07-09 11:06:54 +000064// Cast the given object to a boolean and store it in a variable with
65// the given name. If the object is not a boolean call IllegalOperation
66// and return.
67#define CONVERT_BOOLEAN_CHECKED(name, obj) \
68 RUNTIME_ASSERT(obj->IsBoolean()); \
69 bool name = (obj)->IsTrue();
70
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000071// Cast the given object to a double and store it in a variable with
72// the given name. If the object is not a number (as opposed to
73// the number not-a-number) call IllegalOperation and return.
74#define CONVERT_DOUBLE_CHECKED(name, obj) \
75 RUNTIME_ASSERT(obj->IsNumber()); \
76 double name = (obj)->Number();
77
78// Call the specified converter on the object *comand store the result in
79// a variable of the specified type with the given name. If the
80// object is not a Number call IllegalOperation and return.
81#define CONVERT_NUMBER_CHECKED(type, name, Type, obj) \
82 RUNTIME_ASSERT(obj->IsNumber()); \
83 type name = NumberTo##Type(obj);
84
85// Non-reentrant string buffer for efficient general use in this file.
86static StaticResource<StringInputBuffer> string_input_buffer;
87
88
89static Object* IllegalOperation() {
90 return Top::Throw(Heap::illegal_access_symbol());
91}
92
93
94static Object* Runtime_CloneObjectLiteralBoilerplate(Arguments args) {
95 CONVERT_CHECKED(JSObject, boilerplate, args[0]);
96
97#ifdef DEBUG
98 // Verify the constructor of the boilerplate is equal to the
99 // object function in the CURRENT global_context.
100 CHECK(boilerplate->map()->constructor()
101 == Top::context()->global_context()->object_function());
102#endif
103 return boilerplate->Copy();
104}
105
106
107static Object* Runtime_CreateObjectLiteralBoilerplate(Arguments args) {
108 HandleScope scope;
109 ASSERT(args.length() == 3);
110 // Copy the arguments.
111 Handle<FixedArray> literals = args.at<FixedArray>(0);
112 int literals_index = Smi::cast(args[1])->value();
113 Handle<FixedArray> constant_properties = args.at<FixedArray>(2);
114
115 // Create the boilerplate object for the function literal
116 Handle<JSObject> boilerplate =
117 Factory::NewJSObject(Top::object_function(), TENURED);
118
119 { // Add the constant propeties to the boilerplate.
120 int length = constant_properties->length();
121 OptimizedObjectForAddingMultipleProperties opt(boilerplate, true);
122 for (int index = 0; index < length; index +=2) {
123 Handle<Object> key(constant_properties->get(index+0));
124 Handle<Object> value(constant_properties->get(index+1));
125 uint32_t element_index = 0;
126 if (key->IsSymbol()) {
127 // If key is a symbol it is not an array element.
128 Handle<String> name(String::cast(*key));
129 ASSERT(!name->AsArrayIndex(&element_index));
130 SetProperty(boilerplate, name, value, NONE);
131 } else if (Array::IndexFromObject(*key, &element_index)) {
132 // Array index (uint32).
133 SetElement(boilerplate, element_index, value);
134 } else {
135 // Non-uint32 number.
136 ASSERT(key->IsNumber());
137 double num = key->Number();
138 char arr[100];
139 Vector<char> buffer(arr, ARRAY_SIZE(arr));
140 const char* str = DoubleToCString(num, buffer);
141 Handle<String> name = Factory::NewStringFromAscii(CStrVector(str));
142 SetProperty(boilerplate, name, value, NONE);
143 }
144 }
145 }
146
147 // Update the functions literal and return the boilerplate.
148 literals->set(literals_index, *boilerplate);
149
150 return *boilerplate;
151}
152
153
154static Object* Runtime_CreateArrayLiteral(Arguments args) {
155 // Takes a FixedArray containing literals and produces
156 // JSArray with the elements matching the literals.
157 ASSERT(args.length() == 1);
158 CONVERT_CHECKED(FixedArray, literals, args[0]);
159
160 // Retrieve the array constructor from the global context.
161 JSFunction* constructor =
162 JSFunction::cast(Top::context()->global_context()->array_function());
163
164 // Create the JSArray.
165 Object* object = Heap::AllocateJSObject(constructor);
166 if (object->IsFailure()) return object;
167
168 // Copy the literals.
169 Object* elements = literals->Copy();
170 if (elements->IsFailure()) return elements;
171
172 // Set the elements.
173 JSArray::cast(object)->SetContent(FixedArray::cast(elements));
174 return object;
175}
176
177
178static Object* Runtime_ClassOf(Arguments args) {
179 NoHandleAllocation ha;
180 ASSERT(args.length() == 1);
181 Object* obj = args[0];
182 if (!obj->IsJSObject()) return Heap::null_value();
183 return JSObject::cast(obj)->class_name();
184}
185
186
187static Object* Runtime_IsInPrototypeChain(Arguments args) {
188 NoHandleAllocation ha;
189 ASSERT(args.length() == 2);
190 // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
191 Object* O = args[0];
192 Object* V = args[1];
193 while (true) {
194 Object* prototype = V->GetPrototype();
195 if (prototype->IsNull()) return Heap::false_value();
196 if (O == prototype) return Heap::true_value();
197 V = prototype;
198 }
199}
200
201
202static Object* Runtime_IsConstructCall(Arguments args) {
203 NoHandleAllocation ha;
204 JavaScriptFrameIterator it;
205 return Heap::ToBoolean(it.frame()->IsConstructor());
206}
207
208
209static Object* Runtime_GetBuiltins(Arguments args) {
210 NoHandleAllocation ha;
211 return Top::context()->builtins();
212}
213
214
215static Object* Runtime_RegExpCompile(Arguments args) {
216 HandleScope scope; // create a new handle scope
217 ASSERT(args.length() == 3);
218 CONVERT_CHECKED(JSValue, raw_re, args[0]);
219 Handle<JSValue> re(raw_re);
220 CONVERT_CHECKED(String, raw_pattern, args[1]);
221 Handle<String> pattern(raw_pattern);
222 CONVERT_CHECKED(String, raw_flags, args[2]);
223 Handle<String> flags(raw_flags);
224 return *RegExpImpl::JsreCompile(re, pattern, flags);
225}
226
227
228static Object* Runtime_CreateApiFunction(Arguments args) {
229 HandleScope scope;
230 ASSERT(args.length() == 1);
231 CONVERT_CHECKED(FunctionTemplateInfo, raw_data, args[0]);
232 Handle<FunctionTemplateInfo> data(raw_data);
233 return *Factory::CreateApiFunction(data);
234}
235
236
237static Object* Runtime_IsTemplate(Arguments args) {
238 ASSERT(args.length() == 1);
239 Object* arg = args[0];
240 bool result = arg->IsObjectTemplateInfo()
241 || arg->IsFunctionTemplateInfo();
242 return Heap::ToBoolean(result);
243}
244
245
246static Object* Runtime_GetTemplateField(Arguments args) {
247 ASSERT(args.length() == 2);
248 CONVERT_CHECKED(HeapObject, templ, args[0]);
249 RUNTIME_ASSERT(templ->IsStruct());
250 CONVERT_CHECKED(Smi, field, args[1]);
251 return HeapObject::GetHeapObjectField(templ, field->value());
252}
253
254
255static Object* ThrowRedeclarationError(const char* type, Handle<String> name) {
256 HandleScope scope;
257 Handle<Object> type_handle = Factory::NewStringFromAscii(CStrVector(type));
258 Handle<Object> args[2] = { type_handle, name };
259 Handle<Object> error =
260 Factory::NewTypeError("redeclaration", HandleVector(args, 2));
261 return Top::Throw(*error);
262}
263
264
265static Object* Runtime_DeclareGlobals(Arguments args) {
266 HandleScope scope;
267 Handle<GlobalObject> global = Handle<GlobalObject>(Top::context()->global());
268
269 CONVERT_ARG_CHECKED(FixedArray, pairs, 0);
270 Handle<Context> context = args.at<Context>(1);
271 bool is_eval = Smi::cast(args[2])->value() == 1;
272
273 // Compute the property attributes. According to ECMA-262, section
274 // 13, page 71, the property must be read-only and
275 // non-deletable. However, neither SpiderMonkey nor KJS creates the
276 // property as read-only, so we don't either.
277 PropertyAttributes base = is_eval ? NONE : DONT_DELETE;
278
279 // Only optimize the object if we intend to add more than 5 properties.
280 OptimizedObjectForAddingMultipleProperties ba(global, pairs->length()/2 > 5);
281
282 // Traverse the name/value pairs and set the properties.
283 int length = pairs->length();
284 for (int i = 0; i < length; i += 2) {
285 HandleScope scope;
286 Handle<String> name(String::cast(pairs->get(i)));
287 Handle<Object> value(pairs->get(i + 1));
288
289 // We have to declare a global const property. To capture we only
290 // assign to it when evaluating the assignment for "const x =
291 // <expr>" the initial value is the hole.
292 bool is_const_property = value->IsTheHole();
293
294 if (value->IsUndefined() || is_const_property) {
295 // Lookup the property in the global object, and don't set the
296 // value of the variable if the property is already there.
297 LookupResult lookup;
298 global->Lookup(*name, &lookup);
299 if (lookup.IsProperty()) {
300 // Determine if the property is local by comparing the holder
301 // against the global object. The information will be used to
302 // avoid throwing re-declaration errors when declaring
303 // variables or constants that exist in the prototype chain.
304 bool is_local = (*global == lookup.holder());
305 // Get the property attributes and determine if the property is
306 // read-only.
307 PropertyAttributes attributes = global->GetPropertyAttribute(*name);
308 bool is_read_only = (attributes & READ_ONLY) != 0;
309 if (lookup.type() == INTERCEPTOR) {
310 // If the interceptor says the property is there, we
311 // just return undefined without overwriting the property.
312 // Otherwise, we continue to setting the property.
313 if (attributes != ABSENT) {
314 // Check if the existing property conflicts with regards to const.
315 if (is_local && (is_read_only || is_const_property)) {
316 const char* type = (is_read_only) ? "const" : "var";
317 return ThrowRedeclarationError(type, name);
318 };
319 // The property already exists without conflicting: Go to
320 // the next declaration.
321 continue;
322 }
323 // Fall-through and introduce the absent property by using
324 // SetProperty.
325 } else {
326 if (is_local && (is_read_only || is_const_property)) {
327 const char* type = (is_read_only) ? "const" : "var";
328 return ThrowRedeclarationError(type, name);
329 }
330 // The property already exists without conflicting: Go to
331 // the next declaration.
332 continue;
333 }
334 }
335 } else {
336 // Copy the function and update its context. Use it as value.
337 Handle<JSFunction> boilerplate = Handle<JSFunction>::cast(value);
338 Handle<JSFunction> function =
339 Factory::NewFunctionFromBoilerplate(boilerplate, context);
340 value = function;
341 }
342
343 LookupResult lookup;
344 global->LocalLookup(*name, &lookup);
345
346 PropertyAttributes attributes = is_const_property
347 ? static_cast<PropertyAttributes>(base | READ_ONLY)
348 : base;
349
350 if (lookup.IsProperty()) {
351 // There's a local property that we need to overwrite because
352 // we're either declaring a function or there's an interceptor
353 // that claims the property is absent.
354
355 // Check for conflicting re-declarations. We cannot have
356 // conflicting types in case of intercepted properties because
357 // they are absent.
358 if (lookup.type() != INTERCEPTOR &&
359 (lookup.IsReadOnly() || is_const_property)) {
360 const char* type = (lookup.IsReadOnly()) ? "const" : "var";
361 return ThrowRedeclarationError(type, name);
362 }
363 SetProperty(global, name, value, attributes);
364 } else {
365 // If a property with this name does not already exist on the
366 // global object add the property locally. We take special
367 // precautions to always add it as a local property even in case
368 // of callbacks in the prototype chain (this rules out using
369 // SetProperty). Also, we must use the handle-based version to
370 // avoid GC issues.
371 AddProperty(global, name, value, attributes);
372 }
373 }
374 // Done.
375 return Heap::undefined_value();
376}
377
378
379static Object* Runtime_DeclareContextSlot(Arguments args) {
380 HandleScope scope;
381 ASSERT(args.length() == 5);
382
383 // args[0] is result (TOS)
384 CONVERT_ARG_CHECKED(Context, context, 1);
385 Handle<String> name(String::cast(args[2]));
386 PropertyAttributes mode =
387 static_cast<PropertyAttributes>(Smi::cast(args[3])->value());
388 ASSERT(mode == READ_ONLY || mode == NONE);
389 Handle<Object> initial_value(args[4]);
390
391 // Declarations are always done in the function context.
392 context = Handle<Context>(context->fcontext());
393
394 int index;
395 PropertyAttributes attributes;
396 ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
397 Handle<Object> context_obj =
398 context->Lookup(name, flags, &index, &attributes);
399
400 if (attributes != ABSENT) {
401 // The name was declared before; check for conflicting
402 // re-declarations: This is similar to the code in parser.cc in
403 // the AstBuildingParser::Declare function.
404 if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) {
405 // Functions are not read-only.
406 ASSERT(mode != READ_ONLY || initial_value->IsTheHole());
407 const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var";
408 return ThrowRedeclarationError(type, name);
409 }
410
411 // Initialize it if necessary.
412 if (*initial_value != NULL) {
413 if (index >= 0) {
414 // The variable or constant context slot should always be in
415 // the function context; not in any outer context nor in the
416 // arguments object.
417 ASSERT(context_obj.is_identical_to(context));
418 if (((attributes & READ_ONLY) == 0) ||
419 context->get(index)->IsTheHole()) {
420 context->set(index, *initial_value);
421 }
422 } else {
423 // Slow case: The property is not in the FixedArray part of the context.
424 Handle<JSObject> context_ext = Handle<JSObject>::cast(context_obj);
425 SetProperty(context_ext, name, initial_value, mode);
426 }
427 }
428 return args[0]; // return TOS
429 }
430
431 // The property is not in the function context. It needs to be "declared"
432 // in the function context's extension context, or in the global context.
433 Handle<JSObject> context_ext;
434 if (context->extension() != NULL) {
435 // The function context's extension context exists - use it.
436 context_ext = Handle<JSObject>(context->extension());
437 } else {
438 // The function context's extension context does not exists - allocate it.
439 context_ext = Factory::NewJSObject(Top::context_extension_function());
440 // And store it in the extension slot.
441 context->set_extension(*context_ext);
442 }
443 ASSERT(*context_ext != NULL);
444
445 // Declare the property by setting it to the initial value if provided,
446 // or undefined, and use the correct mode (e.g. READ_ONLY attribute for
447 // constant declarations).
448 ASSERT(!context_ext->HasLocalProperty(*name));
449 Handle<Object> value(Heap::undefined_value());
450 if (*initial_value != NULL) value = initial_value;
451 SetProperty(context_ext, name, value, mode);
452 ASSERT(context_ext->GetLocalPropertyAttribute(*name) == mode);
453 return args[0]; // return TOS
454}
455
456
457static Object* Runtime_InitializeVarGlobal(Arguments args) {
458 NoHandleAllocation nha;
459
460 // Determine if we need to assign to the variable if it already
461 // exists (based on the number of arguments).
462 RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
463 bool assign = args.length() == 2;
464
465 CONVERT_ARG_CHECKED(String, name, 0);
466 GlobalObject* global = Top::context()->global();
467
468 // According to ECMA-262, section 12.2, page 62, the property must
469 // not be deletable.
470 PropertyAttributes attributes = DONT_DELETE;
471
472 // Lookup the property locally in the global object. If it isn't
473 // there, we add the property and take special precautions to always
474 // add it as a local property even in case of callbacks in the
475 // prototype chain (this rules out using SetProperty).
476 LookupResult lookup;
477 global->LocalLookup(*name, &lookup);
478 if (!lookup.IsProperty()) {
479 Object* value = (assign) ? args[1] : Heap::undefined_value();
480 return global->AddProperty(*name, value, attributes);
481 }
482
483 // Determine if this is a redeclaration of something read-only.
484 if (lookup.IsReadOnly()) {
485 return ThrowRedeclarationError("const", name);
486 }
487
488 // Determine if this is a redeclaration of an intercepted read-only
489 // property and figure out if the property exists at all.
490 bool found = true;
491 PropertyType type = lookup.type();
492 if (type == INTERCEPTOR) {
493 PropertyAttributes intercepted = global->GetPropertyAttribute(*name);
494 if (intercepted == ABSENT) {
495 // The interceptor claims the property isn't there. We need to
496 // make sure to introduce it.
497 found = false;
498 } else if ((intercepted & READ_ONLY) != 0) {
499 // The property is present, but read-only. Since we're trying to
500 // overwrite it with a variable declaration we must throw a
501 // re-declaration error.
502 return ThrowRedeclarationError("const", name);
503 }
504 // Restore global object from context (in case of GC).
505 global = Top::context()->global();
506 }
507
508 if (found && !assign) {
509 // The global property is there and we're not assigning any value
510 // to it. Just return.
511 return Heap::undefined_value();
512 }
513
514 // Assign the value (or undefined) to the property.
515 Object* value = (assign) ? args[1] : Heap::undefined_value();
516 return global->SetProperty(&lookup, *name, value, attributes);
517}
518
519
520static Object* Runtime_InitializeConstGlobal(Arguments args) {
521 // All constants are declared with an initial value. The name
522 // of the constant is the first argument and the initial value
523 // is the second.
524 RUNTIME_ASSERT(args.length() == 2);
525 CONVERT_ARG_CHECKED(String, name, 0);
526 Handle<Object> value = args.at<Object>(1);
527
528 // Get the current global object from top.
529 GlobalObject* global = Top::context()->global();
530
531 // According to ECMA-262, section 12.2, page 62, the property must
532 // not be deletable. Since it's a const, it must be READ_ONLY too.
533 PropertyAttributes attributes =
534 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
535
536 // Lookup the property locally in the global object. If it isn't
537 // there, we add the property and take special precautions to always
538 // add it as a local property even in case of callbacks in the
539 // prototype chain (this rules out using SetProperty).
540 LookupResult lookup;
541 global->LocalLookup(*name, &lookup);
542 if (!lookup.IsProperty()) {
543 return global->AddProperty(*name, *value, attributes);
544 }
545
546 // Determine if this is a redeclaration of something not
547 // read-only. In case the result is hidden behind an interceptor we
548 // need to ask it for the property attributes.
549 if (!lookup.IsReadOnly()) {
550 if (lookup.type() != INTERCEPTOR) {
551 return ThrowRedeclarationError("var", name);
552 }
553
554 PropertyAttributes intercepted = global->GetPropertyAttribute(*name);
555
556 // Throw re-declaration error if the intercepted property is present
557 // but not read-only.
558 if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
559 return ThrowRedeclarationError("var", name);
560 }
561
562 // Restore global object from context (in case of GC) and continue
563 // with setting the value because the property is either absent or
564 // read-only. We also have to do redo the lookup.
565 global = Top::context()->global();
566
567 // BUG 1213579: Handle the case where we have to set a read-only
568 // property through an interceptor and only do it if it's
569 // uninitialized, e.g. the hole. Nirk...
570 global->SetProperty(*name, *value, attributes);
571 return *value;
572 }
573
574 // Set the value, but only we're assigning the initial value to a
575 // constant. For now, we determine this by checking if the
576 // current value is the hole.
577 PropertyType type = lookup.type();
578 if (type == FIELD) {
579 FixedArray* properties = global->properties();
580 int index = lookup.GetFieldIndex();
581 if (properties->get(index)->IsTheHole()) {
582 properties->set(index, *value);
583 }
584 } else if (type == NORMAL) {
585 Dictionary* dictionary = global->property_dictionary();
586 int entry = lookup.GetDictionaryEntry();
587 if (dictionary->ValueAt(entry)->IsTheHole()) {
588 dictionary->ValueAtPut(entry, *value);
589 }
590 } else {
591 // Ignore re-initialization of constants that have already been
592 // assigned a function value.
593 ASSERT(lookup.IsReadOnly() && type == CONSTANT_FUNCTION);
594 }
595
596 // Use the set value as the result of the operation.
597 return *value;
598}
599
600
601static Object* Runtime_InitializeConstContextSlot(Arguments args) {
602 HandleScope scope;
603 ASSERT(args.length() == 3);
604
605 Handle<Object> value(args[0]);
606 ASSERT(!value->IsTheHole());
607 CONVERT_ARG_CHECKED(Context, context, 1);
608 Handle<String> name(String::cast(args[2]));
609
610 // Initializations are always done in the function context.
611 context = Handle<Context>(context->fcontext());
612
613 int index;
614 PropertyAttributes attributes;
615 ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
616 Handle<Object> context_obj =
617 context->Lookup(name, flags, &index, &attributes);
618
619 // The property should always be present. It is always declared
620 // before being initialized through DeclareContextSlot.
621 ASSERT(attributes != ABSENT && (attributes & READ_ONLY) != 0);
622
623 // If the slot is in the context, we set it but only if it hasn't
624 // been set before.
625 if (index >= 0) {
626 // The constant context slot should always be in the function
627 // context; not in any outer context nor in the arguments object.
628 ASSERT(context_obj.is_identical_to(context));
629 if (context->get(index)->IsTheHole()) {
630 context->set(index, *value);
631 }
632 return *value;
633 }
634
635 // Otherwise, the slot must be in a JS object extension.
636 Handle<JSObject> context_ext(JSObject::cast(*context_obj));
637
638 // We must initialize the value only if it wasn't initialized
639 // before, e.g. for const declarations in a loop. The property has
640 // the hole value if it wasn't initialized yet. NOTE: We cannot use
641 // GetProperty() to get the current value as it 'unholes' the value.
642 LookupResult lookup;
643 context_ext->LocalLookupRealNamedProperty(*name, &lookup);
644 ASSERT(lookup.IsProperty()); // the property was declared
645 ASSERT(lookup.IsReadOnly()); // and it was declared as read-only
646
647 PropertyType type = lookup.type();
648 if (type == FIELD) {
649 FixedArray* properties = context_ext->properties();
650 int index = lookup.GetFieldIndex();
651 if (properties->get(index)->IsTheHole()) {
652 properties->set(index, *value);
653 }
654 } else if (type == NORMAL) {
655 Dictionary* dictionary = context_ext->property_dictionary();
656 int entry = lookup.GetDictionaryEntry();
657 if (dictionary->ValueAt(entry)->IsTheHole()) {
658 dictionary->ValueAtPut(entry, *value);
659 }
660 } else {
661 // We should not reach here. Any real, named property should be
662 // either a field or a dictionary slot.
663 UNREACHABLE();
664 }
665 return *value;
666}
667
668
669static Object* Runtime_RegExpExec(Arguments args) {
670 HandleScope scope;
671 ASSERT(args.length() == 3);
672 CONVERT_CHECKED(JSValue, raw_regexp, args[0]);
673 Handle<JSValue> regexp(raw_regexp);
674 CONVERT_CHECKED(String, raw_subject, args[1]);
675 Handle<String> subject(raw_subject);
676 Handle<Object> index(args[2]);
677 ASSERT(index->IsNumber());
678 return *RegExpImpl::JsreExec(regexp, subject, index);
679}
680
681
682static Object* Runtime_RegExpExecGlobal(Arguments args) {
683 HandleScope scope;
684 ASSERT(args.length() == 2);
685 CONVERT_CHECKED(JSValue, raw_regexp, args[0]);
686 Handle<JSValue> regexp(raw_regexp);
687 CONVERT_CHECKED(String, raw_subject, args[1]);
688 Handle<String> subject(raw_subject);
689 return *RegExpImpl::JsreExecGlobal(regexp, subject);
690}
691
692
693static Object* Runtime_MaterializeRegExpLiteral(Arguments args) {
694 HandleScope scope;
695 ASSERT(args.length() == 4);
696 CONVERT_ARG_CHECKED(FixedArray, literals, 0);
697 int index = Smi::cast(args[1])->value();
698 Handle<String> pattern = args.at<String>(2);
699 Handle<String> flags = args.at<String>(3);
700
701 // Compute the regular expression literal.
702 bool has_pending_exception;
703 Handle<Object> regexp =
704 RegExpImpl::CreateRegExpLiteral(pattern, flags, &has_pending_exception);
705 if (has_pending_exception) {
706 ASSERT(Top::has_pending_exception());
707 return Failure::Exception();
708 }
709 literals->set(index, *regexp);
710 return *regexp;
711}
712
713
714static Object* Runtime_FunctionGetName(Arguments args) {
715 NoHandleAllocation ha;
716 ASSERT(args.length() == 1);
717
718 CONVERT_CHECKED(JSFunction, f, args[0]);
719 return f->shared()->name();
720}
721
722
723static Object* Runtime_FunctionGetScript(Arguments args) {
724 HandleScope scope;
725 ASSERT(args.length() == 1);
726
727 CONVERT_CHECKED(JSFunction, fun, args[0]);
728 Handle<Object> script = Handle<Object>(fun->shared()->script());
729 if (!script->IsScript()) return Heap::undefined_value();
730
731 return *GetScriptWrapper(Handle<Script>::cast(script));
732}
733
734
735static Object* Runtime_FunctionGetSourceCode(Arguments args) {
736 NoHandleAllocation ha;
737 ASSERT(args.length() == 1);
738
739 CONVERT_CHECKED(JSFunction, f, args[0]);
740 return f->shared()->GetSourceCode();
741}
742
743
744static Object* Runtime_FunctionGetScriptSourcePosition(Arguments args) {
745 NoHandleAllocation ha;
746 ASSERT(args.length() == 1);
747
748 CONVERT_CHECKED(JSFunction, fun, args[0]);
749 int pos = fun->shared()->start_position();
750 return Smi::FromInt(pos);
751}
752
753
754static Object* Runtime_FunctionSetInstanceClassName(Arguments args) {
755 NoHandleAllocation ha;
756 ASSERT(args.length() == 2);
757
758 CONVERT_CHECKED(JSFunction, fun, args[0]);
759 CONVERT_CHECKED(String, name, args[1]);
760 fun->SetInstanceClassName(name);
761 return Heap::undefined_value();
762}
763
764
765static Object* Runtime_FunctionSetLength(Arguments args) {
766 NoHandleAllocation ha;
767 ASSERT(args.length() == 2);
768
769 CONVERT_CHECKED(JSFunction, fun, args[0]);
770 CONVERT_CHECKED(Smi, length, args[1]);
771 fun->shared()->set_length(length->value());
772 return length;
773}
774
775
776static Object* Runtime_FunctionSetPrototype(Arguments args) {
777 HandleScope scope;
778 ASSERT(args.length() == 2);
779
780 CONVERT_CHECKED(JSFunction, fun, args[0]);
781 Accessors::FunctionSetPrototype(fun, args[1], NULL);
782 return args[0]; // return TOS
783}
784
785
786static Object* Runtime_SetCode(Arguments args) {
787 HandleScope scope;
788 ASSERT(args.length() == 2);
789
790 CONVERT_CHECKED(JSFunction, raw_target, args[0]);
791 Handle<JSFunction> target(raw_target);
792 Handle<Object> code = args.at<Object>(1);
793
794 Handle<Context> context(target->context());
795
796 if (!code->IsNull()) {
797 RUNTIME_ASSERT(code->IsJSFunction());
798 Handle<JSFunction> fun = Handle<JSFunction>::cast(code);
799 SetExpectedNofProperties(target, fun->shared()->expected_nof_properties());
800 if (!fun->is_compiled() && !CompileLazy(fun, KEEP_EXCEPTION)) {
801 return Failure::Exception();
802 }
803 // Set the code, formal parameter count, and the length of the target
804 // function.
805 target->set_code(fun->code());
806 target->shared()->set_length(fun->shared()->length());
807 target->shared()->set_formal_parameter_count(
808 fun->shared()->formal_parameter_count());
809 context = Handle<Context>(fun->context());
810
811 // Make sure we get a fresh copy of the literal vector to avoid
812 // cross context contamination.
813 int number_of_literals = fun->literals()->length();
814 if (number_of_literals > 0) {
815 Handle<FixedArray> literals =
816 Factory::NewFixedArray(number_of_literals, TENURED);
817 target->set_literals(*literals);
818 }
819 }
820
821 target->set_context(*context);
822 return *target;
823}
824
825
826static Object* CharCodeAt(String* subject, Object* index) {
827 uint32_t i = 0;
828 if (!Array::IndexFromObject(index, &i))
829 return Heap::nan_value();
830 // Flatten the string. If someone wants to get a char at an index
831 // in a cons string, it is likely that more indices will be
832 // accessed.
833 subject->TryFlatten();
834 if (i >= static_cast<uint32_t>(subject->length()))
835 return Heap::nan_value();
836 return Smi::FromInt(subject->Get(i));
837}
838
839
840static Object* Runtime_StringCharCodeAt(Arguments args) {
841 NoHandleAllocation ha;
842 ASSERT(args.length() == 2);
843
844 CONVERT_CHECKED(String, subject, args[0]);
845 Object* index = args[1];
846 return CharCodeAt(subject, index);
847}
848
849
850static Object* Runtime_CharFromCode(Arguments args) {
851 NoHandleAllocation ha;
852 ASSERT(args.length() == 1);
853 uint32_t code;
854 if (Array::IndexFromObject(args[0], &code)) {
855 if (code <= 0xffff) {
856 return Heap::LookupSingleCharacterStringFromCode(code);
857 }
858 }
859 return Heap::empty_string();
860}
861
862
863static inline void ComputeKMPNextTable(String* pattern, int next_table[]) {
864 int i = 0;
865 int j = -1;
866 next_table[0] = -1;
867
868 Access<StringInputBuffer> buffer(&string_input_buffer);
869 buffer->Reset(pattern);
870 int length = pattern->length();
871 uint16_t p = buffer->GetNext();
872 while (i < length - 1) {
873 while (j > -1 && p != pattern->Get(j)) {
874 j = next_table[j];
875 }
876 i++;
877 j++;
878 p = buffer->GetNext();
879 if (p == pattern->Get(j)) {
880 next_table[i] = next_table[j];
881 } else {
882 next_table[i] = j;
883 }
884 }
885}
886
887
888static Object* Runtime_StringIndexOf(Arguments args) {
889 NoHandleAllocation ha;
890 ASSERT(args.length() == 3);
891
892 CONVERT_CHECKED(String, sub, args[0]);
893 CONVERT_CHECKED(String, pat, args[1]);
894 Object* index = args[2];
895
896 int subject_length = sub->length();
897 int pattern_length = pat->length();
898
899 sub->TryFlatten();
900 pat->TryFlatten();
901
902 uint32_t start_index;
903 if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1);
904 if (pattern_length == 0) return Smi::FromInt(start_index);
905
906 // Searching for one specific character is common. For one
907 // character patterns the KMP algorithm is guaranteed to slow down
908 // the search, so we just run through the subject string.
909 if (pattern_length == 1) {
910 uint16_t pattern_char = pat->Get(0);
911 for (int i = start_index; i < subject_length; i++) {
912 if (sub->Get(i) == pattern_char) {
913 return Smi::FromInt(i);
914 }
915 }
916 return Smi::FromInt(-1);
917 }
918
919 // For patterns with a length larger than one character we use the KMP
920 // algorithm.
921 //
922 // Compute the 'next' table.
923 int* next_table = NewArray<int>(pattern_length);
924 ComputeKMPNextTable(pat, next_table);
925 // Search using the 'next' table.
926 int pattern_index = 0;
927 // We would like to use StringInputBuffer here, but it does not have
928 // the ability to start anywhere but the first character of a
929 // string. It would be nice to have efficient forward-seeking
930 // support on StringInputBuffers.
931 int subject_index = start_index;
932 while (subject_index < subject_length) {
933 uint16_t subject_char = sub->Get(subject_index);
934 while (pattern_index > -1 && pat->Get(pattern_index) != subject_char) {
935 pattern_index = next_table[pattern_index];
936 }
937 pattern_index++;
938 subject_index++;
939 if (pattern_index >= pattern_length) {
940 DeleteArray(next_table);
941 return Smi::FromInt(subject_index - pattern_index);
942 }
943 }
944 DeleteArray(next_table);
945 return Smi::FromInt(-1);
946}
947
948
949static Object* Runtime_StringLastIndexOf(Arguments args) {
950 NoHandleAllocation ha;
951 ASSERT(args.length() == 3);
952
953 CONVERT_CHECKED(String, sub, args[0]);
954 CONVERT_CHECKED(String, pat, args[1]);
955 Object* index = args[2];
956
957 sub->TryFlatten();
958 pat->TryFlatten();
959
960 uint32_t start_index;
961 if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1);
962
963 uint32_t pattern_length = pat->length();
964 uint32_t sub_length = sub->length();
965
kasper.lundbd3ec4e2008-07-09 11:06:54 +0000966 if (start_index + pattern_length > sub_length) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000967 start_index = sub_length - pattern_length;
kasper.lundbd3ec4e2008-07-09 11:06:54 +0000968 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000969
970 for (int i = start_index; i >= 0; i--) {
971 bool found = true;
972 for (uint32_t j = 0; j < pattern_length; j++) {
973 if (sub->Get(i + j) != pat->Get(j)) {
974 found = false;
975 break;
976 }
977 }
978 if (found) return Smi::FromInt(i);
979 }
980
981 return Smi::FromInt(-1);
982}
983
984
985static Object* Runtime_StringLocaleCompare(Arguments args) {
986 NoHandleAllocation ha;
987 ASSERT(args.length() == 2);
988
989 CONVERT_CHECKED(String, str1, args[0]);
990 CONVERT_CHECKED(String, str2, args[1]);
991
992 if (str1 == str2) return Smi::FromInt(0); // Equal.
993 int str1_length = str1->length();
994 int str2_length = str2->length();
995
996 // Decide trivial cases without flattening.
997 if (str1_length == 0) {
998 if (str2_length == 0) return Smi::FromInt(0); // Equal.
999 return Smi::FromInt(-str2_length);
1000 } else {
1001 if (str2_length == 0) return Smi::FromInt(str1_length);
1002 }
1003
1004 int end = str1_length < str2_length ? str1_length : str2_length;
1005
1006 // No need to flatten if we are going to find the answer on the first
1007 // character. At this point we know there is at least one character
1008 // in each string, due to the trivial case handling above.
1009 int d = str1->Get(0) - str2->Get(0);
1010 if (d != 0) return Smi::FromInt(d);
1011
1012 str1->TryFlatten();
1013 str2->TryFlatten();
1014
1015 static StringInputBuffer buf1;
1016 static StringInputBuffer buf2;
1017
1018 buf1.Reset(str1);
1019 buf2.Reset(str2);
1020
1021 for (int i = 0; i < end; i++) {
1022 uint16_t char1 = buf1.GetNext();
1023 uint16_t char2 = buf2.GetNext();
1024 if (char1 != char2) return Smi::FromInt(char1 - char2);
1025 }
1026
1027 return Smi::FromInt(str1_length - str2_length);
1028}
1029
1030
1031static Object* Runtime_StringSlice(Arguments args) {
1032 NoHandleAllocation ha;
1033 ASSERT(args.length() == 3);
1034
1035 CONVERT_CHECKED(String, value, args[0]);
1036 CONVERT_DOUBLE_CHECKED(from_number, args[1]);
1037 CONVERT_DOUBLE_CHECKED(to_number, args[2]);
1038
1039 int start = FastD2I(from_number);
1040 int end = FastD2I(to_number);
1041
1042 RUNTIME_ASSERT(end >= start);
1043 RUNTIME_ASSERT(start >= 0);
1044 RUNTIME_ASSERT(end <= value->length());
1045 return value->Slice(start, end);
1046}
1047
1048
1049static Object* Runtime_NumberToRadixString(Arguments args) {
1050 NoHandleAllocation ha;
1051 ASSERT(args.length() == 2);
1052
1053 CONVERT_DOUBLE_CHECKED(value, args[0]);
1054 if (isnan(value)) {
1055 return Heap::AllocateStringFromAscii(CStrVector("NaN"));
1056 }
1057 if (isinf(value)) {
1058 if (value < 0) {
1059 return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
1060 }
1061 return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
1062 }
1063 CONVERT_DOUBLE_CHECKED(radix_number, args[1]);
1064 int radix = FastD2I(radix_number);
1065 RUNTIME_ASSERT(2 <= radix && radix <= 36);
1066 char* str = DoubleToRadixCString(value, radix);
1067 Object* result = Heap::AllocateStringFromAscii(CStrVector(str));
1068 DeleteArray(str);
1069 return result;
1070}
1071
1072
1073static Object* Runtime_NumberToFixed(Arguments args) {
1074 NoHandleAllocation ha;
1075 ASSERT(args.length() == 2);
1076
1077 CONVERT_DOUBLE_CHECKED(value, args[0]);
1078 if (isnan(value)) {
1079 return Heap::AllocateStringFromAscii(CStrVector("NaN"));
1080 }
1081 if (isinf(value)) {
1082 if (value < 0) {
1083 return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
1084 }
1085 return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
1086 }
1087 CONVERT_DOUBLE_CHECKED(f_number, args[1]);
1088 int f = FastD2I(f_number);
1089 RUNTIME_ASSERT(f >= 0);
1090 char* str = DoubleToFixedCString(value, f);
1091 Object* res = Heap::AllocateStringFromAscii(CStrVector(str));
1092 DeleteArray(str);
1093 return res;
1094}
1095
1096
1097static Object* Runtime_NumberToExponential(Arguments args) {
1098 NoHandleAllocation ha;
1099 ASSERT(args.length() == 2);
1100
1101 CONVERT_DOUBLE_CHECKED(value, args[0]);
1102 if (isnan(value)) {
1103 return Heap::AllocateStringFromAscii(CStrVector("NaN"));
1104 }
1105 if (isinf(value)) {
1106 if (value < 0) {
1107 return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
1108 }
1109 return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
1110 }
1111 CONVERT_DOUBLE_CHECKED(f_number, args[1]);
1112 int f = FastD2I(f_number);
1113 RUNTIME_ASSERT(f >= -1 && f <= 20);
1114 char* str = DoubleToExponentialCString(value, f);
1115 Object* res = Heap::AllocateStringFromAscii(CStrVector(str));
1116 DeleteArray(str);
1117 return res;
1118}
1119
1120
1121static Object* Runtime_NumberToPrecision(Arguments args) {
1122 NoHandleAllocation ha;
1123 ASSERT(args.length() == 2);
1124
1125 CONVERT_DOUBLE_CHECKED(value, args[0]);
1126 if (isnan(value)) {
1127 return Heap::AllocateStringFromAscii(CStrVector("NaN"));
1128 }
1129 if (isinf(value)) {
1130 if (value < 0) {
1131 return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
1132 }
1133 return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
1134 }
1135 CONVERT_DOUBLE_CHECKED(f_number, args[1]);
1136 int f = FastD2I(f_number);
1137 RUNTIME_ASSERT(f >= 1 && f <= 21);
1138 char* str = DoubleToPrecisionCString(value, f);
1139 Object* res = Heap::AllocateStringFromAscii(CStrVector(str));
1140 DeleteArray(str);
1141 return res;
1142}
1143
1144
1145// Returns a single character string where first character equals
1146// string->Get(index).
1147static Object* GetCharAt(String* string, uint32_t index) {
1148 if (index < static_cast<uint32_t>(string->length())) {
1149 string->TryFlatten();
1150 return Heap::LookupSingleCharacterStringFromCode(string->Get(index));
1151 }
1152 return *Execution::CharAt(Handle<String>(string), index);
1153}
1154
1155
1156Object* Runtime::GetElementOrCharAt(Handle<Object> object, uint32_t index) {
1157 // Handle [] indexing on Strings
1158 if (object->IsString()) {
1159 Object* result = GetCharAt(String::cast(*object), index);
1160 if (!result->IsUndefined()) return result;
1161 }
1162
1163 // Handle [] indexing on String objects
1164 if (object->IsStringObjectWithCharacterAt(index)) {
1165 JSValue* js_value = JSValue::cast(*object);
1166 Object* result = GetCharAt(String::cast(js_value->value()), index);
1167 if (!result->IsUndefined()) return result;
1168 }
1169
1170 if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
1171 Object* prototype = object->GetPrototype();
1172 return prototype->GetElement(index);
1173 }
1174
1175 return object->GetElement(index);
1176}
1177
1178
1179Object* Runtime::GetObjectProperty(Handle<Object> object, Object* key) {
1180 if (object->IsUndefined() || object->IsNull()) {
1181 HandleScope scope;
1182 Handle<Object> key_handle(key);
1183 Handle<Object> args[2] = { key_handle, object };
1184 Handle<Object> error =
1185 Factory::NewTypeError("non_object_property_load",
1186 HandleVector(args, 2));
1187 return Top::Throw(*error);
1188 }
1189
1190 // Check if the given key is an array index.
1191 uint32_t index;
1192 if (Array::IndexFromObject(key, &index)) {
1193 HandleScope scope;
1194 return GetElementOrCharAt(object, index);
1195 }
1196
1197 // Convert the key to a string - possibly by calling back into JavaScript.
1198 String* name;
1199 if (key->IsString()) {
1200 name = String::cast(key);
1201 } else {
1202 HandleScope scope;
1203 bool has_pending_exception = false;
1204 Handle<Object> converted =
1205 Execution::ToString(Handle<Object>(key), &has_pending_exception);
1206 if (has_pending_exception) return Failure::Exception();
1207 name = String::cast(*converted);
1208 }
1209
1210 // Check if the name is trivially convertable to an index and get
1211 // the element if so.
1212 if (name->AsArrayIndex(&index)) {
1213 HandleScope scope;
1214 return GetElementOrCharAt(object, index);
1215 } else {
1216 PropertyAttributes attr;
1217 return object->GetProperty(name, &attr);
1218 }
1219}
1220
1221
1222static Object* Runtime_GetProperty(Arguments args) {
1223 NoHandleAllocation ha;
1224 ASSERT(args.length() == 2);
1225
1226 Handle<Object> object = args.at<Object>(0);
1227 Object* key = args[1];
1228
1229 return Runtime::GetObjectProperty(object, key);
1230}
1231
1232
1233Object* Runtime::SetObjectProperty(Handle<Object> object,
1234 Handle<Object> key,
1235 Handle<Object> value,
1236 PropertyAttributes attr) {
1237 if (object->IsUndefined() || object->IsNull()) {
1238 HandleScope scope;
1239 Handle<Object> obj(object);
1240 Handle<Object> args[2] = { key, obj };
1241 Handle<Object> error =
1242 Factory::NewTypeError("non_object_property_store",
1243 HandleVector(args, 2));
1244 return Top::Throw(*error);
1245 }
1246
1247 // If the object isn't a JavaScript object, we ignore the store.
1248 if (!object->IsJSObject()) return *value;
1249
1250 // Check if the given key is an array index.
1251 uint32_t index;
1252 if (Array::IndexFromObject(*key, &index)) {
1253 ASSERT(attr == NONE);
1254
1255 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
1256 // of a string using [] notation. We need to support this too in
1257 // JavaScript.
1258 // In the case of a String object we just need to redirect the assignment to
1259 // the underlying string if the index is in range. Since the underlying
1260 // string does nothing with the assignment then we can ignore such
1261 // assignments.
1262 if (object->IsStringObjectWithCharacterAt(index))
1263 return *value;
1264
1265 Object* result = JSObject::cast(*object)->SetElement(index, *value);
1266 if (result->IsFailure()) return result;
1267 return *value;
1268 }
1269
1270 if (key->IsString()) {
1271 Object* result;
1272 if (String::cast(*key)->AsArrayIndex(&index)) {
1273 ASSERT(attr == NONE);
1274 result = JSObject::cast(*object)->SetElement(index, *value);
1275 } else {
1276 String::cast(*key)->TryFlatten();
1277 result =
1278 JSObject::cast(*object)->SetProperty(String::cast(*key), *value,
1279 attr);
1280 }
1281 if (result->IsFailure()) return result;
1282 return *value;
1283 }
1284
1285 // Handlify object and value before calling into JavaScript again.
1286 Handle<JSObject> object_handle = Handle<JSObject>::cast(object);
1287 Handle<Object> value_handle = value;
1288
1289 // Call-back into JavaScript to convert the key to a string.
1290 HandleScope scope;
1291 bool has_pending_exception = false;
1292 Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
1293 if (has_pending_exception) return Failure::Exception();
1294 Handle<String> name = Handle<String>::cast(converted);
1295
1296 if (name->AsArrayIndex(&index)) {
1297 ASSERT(attr == NONE);
1298 return object_handle->SetElement(index, *value_handle);
1299 } else {
1300 return object_handle->SetProperty(*name, *value_handle, attr);
1301 }
1302}
1303
1304
1305static Object* Runtime_AddProperty(Arguments args) {
1306 NoHandleAllocation ha;
1307 ASSERT(args.length() == 4);
1308
1309 CONVERT_CHECKED(JSObject, object, args[0]);
1310 CONVERT_CHECKED(String, name, args[1]);
1311 RUNTIME_ASSERT(!object->HasLocalProperty(name));
1312 CONVERT_CHECKED(Smi, attr_obj, args[3]);
1313
1314 int attr = attr_obj->value();
1315 RUNTIME_ASSERT((attr & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
1316 PropertyAttributes attributes = static_cast<PropertyAttributes>(attr);
1317
1318 return object->AddProperty(name, args[2], attributes);
1319}
1320
1321
1322static Object* Runtime_SetProperty(Arguments args) {
1323 NoHandleAllocation ha;
1324 RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
1325
1326 Handle<Object> object = args.at<Object>(0);
1327 Handle<Object> key = args.at<Object>(1);
1328 Handle<Object> value = args.at<Object>(2);
1329
1330 // Compute attributes.
1331 PropertyAttributes attributes = NONE;
1332 if (args.length() == 4) {
1333 CONVERT_CHECKED(Smi, value_obj, args[3]);
1334 int value = value_obj->value();
1335 // Only attribute bits should be set.
1336 ASSERT((value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
1337 attributes = static_cast<PropertyAttributes>(value);
1338 }
1339 return Runtime::SetObjectProperty(object, key, value, attributes);
1340}
1341
1342
1343// Set a local property, even if it is READ_ONLY. If the property does not
1344// exist, it will be added with attributes NONE.
1345static Object* Runtime_IgnoreAttributesAndSetProperty(Arguments args) {
1346 NoHandleAllocation ha;
1347 ASSERT(args.length() == 3);
1348
1349 CONVERT_CHECKED(JSObject, object, args[0]);
1350 CONVERT_CHECKED(String, name, args[1]);
1351
1352 return object->IgnoreAttributesAndSetLocalProperty(name, args[2]);
1353}
1354
1355
1356static Object* Runtime_DeleteProperty(Arguments args) {
1357 NoHandleAllocation ha;
1358 ASSERT(args.length() == 2);
1359
1360 CONVERT_CHECKED(JSObject, object, args[0]);
1361 CONVERT_CHECKED(String, key, args[1]);
1362 return object->DeleteProperty(key);
1363}
1364
1365
1366static Object* Runtime_HasLocalProperty(Arguments args) {
1367 NoHandleAllocation ha;
1368 ASSERT(args.length() == 2);
1369 CONVERT_CHECKED(String, key, args[1]);
1370
1371 // Only JS objects can have properties.
1372 if (args[0]->IsJSObject()) {
1373 JSObject* object = JSObject::cast(args[0]);
1374 if (object->HasLocalProperty(key)) return Heap::true_value();
1375 } else if (args[0]->IsString()) {
1376 // Well, there is one exception: Handle [] on strings.
1377 uint32_t index;
1378 if (key->AsArrayIndex(&index)) {
1379 String* string = String::cast(args[0]);
1380 if (index < static_cast<uint32_t>(string->length()))
1381 return Heap::true_value();
1382 }
1383 }
1384 return Heap::false_value();
1385}
1386
1387
1388static Object* Runtime_HasProperty(Arguments args) {
1389 NoHandleAllocation na;
1390 ASSERT(args.length() == 2);
1391
1392 // Only JS objects can have properties.
1393 if (args[0]->IsJSObject()) {
1394 JSObject* object = JSObject::cast(args[0]);
1395 CONVERT_CHECKED(String, key, args[1]);
1396 if (object->HasProperty(key)) return Heap::true_value();
1397 }
1398 return Heap::false_value();
1399}
1400
1401
1402static Object* Runtime_HasElement(Arguments args) {
1403 NoHandleAllocation na;
1404 ASSERT(args.length() == 2);
1405
1406 // Only JS objects can have elements.
1407 if (args[0]->IsJSObject()) {
1408 JSObject* object = JSObject::cast(args[0]);
1409 CONVERT_CHECKED(Smi, index_obj, args[1]);
1410 uint32_t index = index_obj->value();
1411 if (object->HasElement(index)) return Heap::true_value();
1412 }
1413 return Heap::false_value();
1414}
1415
1416
1417static Object* Runtime_IsPropertyEnumerable(Arguments args) {
1418 NoHandleAllocation ha;
1419 ASSERT(args.length() == 2);
1420
1421 CONVERT_CHECKED(JSObject, object, args[0]);
1422 CONVERT_CHECKED(String, key, args[1]);
1423
1424 uint32_t index;
1425 if (key->AsArrayIndex(&index)) {
1426 return Heap::ToBoolean(object->HasElement(index));
1427 }
1428
1429 LookupResult result;
1430 object->LocalLookup(key, &result);
1431 if (!result.IsProperty()) return Heap::false_value();
1432 return Heap::ToBoolean(!result.IsDontEnum());
1433}
1434
1435
1436static Object* Runtime_GetPropertyNames(Arguments args) {
1437 HandleScope scope;
1438 ASSERT(args.length() == 1);
1439
1440 CONVERT_CHECKED(JSObject, raw_object, args[0]);
1441 Handle<JSObject> object(raw_object);
1442 return *GetKeysFor(object);
1443}
1444
1445
1446// Returns either a FixedArray as Runtime_GetPropertyNames,
1447// or, if the given object has an enum cache that contains
1448// all enumerable properties of the object and its prototypes
1449// have none, the map of the object. This is used to speed up
1450// the check for deletions during a for-in.
1451static Object* Runtime_GetPropertyNamesFast(Arguments args) {
1452 ASSERT(args.length() == 1);
1453
1454 CONVERT_CHECKED(JSObject, raw_object, args[0]);
1455
1456 if (raw_object->IsSimpleEnum()) return raw_object->map();
1457
1458 HandleScope scope;
1459 Handle<JSObject> object(raw_object);
1460 Handle<FixedArray> content = GetKeysInFixedArrayFor(object);
1461
1462 // Test again, since cache may have been built by preceding call.
1463 if (object->IsSimpleEnum()) return object->map();
1464
1465 return *content;
1466}
1467
1468
1469static Object* Runtime_GetArgumentsProperty(Arguments args) {
1470 NoHandleAllocation ha;
1471 ASSERT(args.length() == 1);
1472
1473 // Compute the frame holding the arguments.
1474 JavaScriptFrameIterator it;
1475 it.AdvanceToArgumentsFrame();
1476 JavaScriptFrame* frame = it.frame();
1477
1478 // Get the actual number of provided arguments.
1479 const uint32_t n = frame->GetProvidedParametersCount();
1480
1481 // Try to convert the key to an index. If successful and within
1482 // index return the the argument from the frame.
1483 uint32_t index;
1484 if (Array::IndexFromObject(args[0], &index) && index < n) {
1485 return frame->GetParameter(index);
1486 }
1487
1488 // Convert the key to a string.
1489 HandleScope scope;
1490 bool exception = false;
1491 Handle<Object> converted =
1492 Execution::ToString(args.at<Object>(0), &exception);
1493 if (exception) return Failure::Exception();
1494 Handle<String> key = Handle<String>::cast(converted);
1495
1496 // Try to convert the string key into an array index.
1497 if (key->AsArrayIndex(&index)) {
1498 if (index < n) {
1499 return frame->GetParameter(index);
1500 } else {
1501 return Top::initial_object_prototype()->GetElement(index);
1502 }
1503 }
1504
1505 // Handle special arguments properties.
1506 if (key->Equals(Heap::length_symbol())) return Smi::FromInt(n);
1507 if (key->Equals(Heap::callee_symbol())) return frame->function();
1508
1509 // Lookup in the initial Object.prototype object.
1510 return Top::initial_object_prototype()->GetProperty(*key);
1511}
1512
1513
1514static Object* Runtime_ToBool(Arguments args) {
1515 NoHandleAllocation ha;
1516 ASSERT(args.length() == 1);
1517
1518 return args[0]->ToBoolean();
1519}
1520
1521
1522// Returns the type string of a value; see ECMA-262, 11.4.3 (p 47).
1523// Possible optimizations: put the type string into the oddballs.
1524static Object* Runtime_Typeof(Arguments args) {
1525 NoHandleAllocation ha;
1526
1527 Object* obj = args[0];
1528 if (obj->IsNumber()) return Heap::number_symbol();
1529 HeapObject* heap_obj = HeapObject::cast(obj);
1530
1531 // typeof an undetectable object is 'undefined'
1532 if (heap_obj->map()->is_undetectable())
1533 return Heap::undefined_symbol();
1534
1535 InstanceType instance_type = heap_obj->map()->instance_type();
1536 if (instance_type < FIRST_NONSTRING_TYPE) {
1537 return Heap::string_symbol();
1538 }
1539
1540 switch (instance_type) {
1541 case ODDBALL_TYPE:
1542 if (heap_obj->IsTrue() || heap_obj->IsFalse()) {
1543 return Heap::boolean_symbol();
1544 }
1545 if (heap_obj->IsNull()) {
1546 return Heap::object_symbol();
1547 }
1548 ASSERT(heap_obj->IsUndefined());
1549 return Heap::undefined_symbol();
1550 case JS_FUNCTION_TYPE:
1551 return Heap::function_symbol();
1552 default:
1553 // For any kind of object not handled above, the spec rule for
1554 // host objects gives that it is okay to return "object"
1555 return Heap::object_symbol();
1556 }
1557}
1558
1559
1560static Object* Runtime_StringToNumber(Arguments args) {
1561 NoHandleAllocation ha;
1562 ASSERT(args.length() == 1);
1563 CONVERT_CHECKED(String, subject, args[0]);
kasper.lundbd3ec4e2008-07-09 11:06:54 +00001564 subject->TryFlatten();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001565 return Heap::NumberFromDouble(StringToDouble(subject, ALLOW_HEX));
1566}
1567
1568
1569static Object* Runtime_StringFromCharCodeArray(Arguments args) {
1570 NoHandleAllocation ha;
1571 ASSERT(args.length() == 1);
1572
1573 CONVERT_CHECKED(JSArray, codes, args[0]);
1574 int length = Smi::cast(codes->length())->value();
1575
1576 // Check if the string can be ASCII.
1577 int i;
1578 for (i = 0; i < length; i++) {
1579 Object* element = codes->GetElement(i);
1580 CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
1581 if ((chr & 0xffff) > String::kMaxAsciiCharCode)
1582 break;
1583 }
1584
1585 Object* object = NULL;
1586 if (i == length) { // The string is ASCII.
1587 object = Heap::AllocateRawAsciiString(length);
1588 } else { // The string is not ASCII.
1589 object = Heap::AllocateRawTwoByteString(length);
1590 }
1591
1592 if (object->IsFailure()) return object;
1593 String* result = String::cast(object);
1594 for (int i = 0; i < length; i++) {
1595 Object* element = codes->GetElement(i);
1596 CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
1597 result->Set(i, chr & 0xffff);
1598 }
1599 return result;
1600}
1601
1602
1603// kNotEscaped is generated by the following:
1604//
1605// #!/bin/perl
1606// for (my $i = 0; $i < 256; $i++) {
1607// print "\n" if $i % 16 == 0;
1608// my $c = chr($i);
1609// my $escaped = 1;
1610// $escaped = 0 if $c =~ m#[A-Za-z0-9@*_+./-]#;
1611// print $escaped ? "0, " : "1, ";
1612// }
1613
1614
1615static bool IsNotEscaped(uint16_t character) {
1616 // Only for 8 bit characters, the rest are always escaped (in a different way)
1617 ASSERT(character < 256);
1618 static const char kNotEscaped[256] = {
1619 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1620 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1621 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1,
1622 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
1623 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1624 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
1625 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1626 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
1627 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1628 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1629 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1630 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1631 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1632 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1633 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1634 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1635 };
1636 return kNotEscaped[character] != 0;
1637}
1638
1639
1640static Object* Runtime_URIEscape(Arguments args) {
1641 const char hex_chars[] = "0123456789ABCDEF";
1642 NoHandleAllocation ha;
1643 ASSERT(args.length() == 1);
1644 CONVERT_CHECKED(String, source, args[0]);
1645
1646 source->TryFlatten();
1647
1648 int escaped_length = 0;
1649 int length = source->length();
1650 {
1651 Access<StringInputBuffer> buffer(&string_input_buffer);
1652 buffer->Reset(source);
1653 while (buffer->has_more()) {
1654 uint16_t character = buffer->GetNext();
1655 if (character >= 256) {
1656 escaped_length += 6;
1657 } else if (IsNotEscaped(character)) {
1658 escaped_length++;
1659 } else {
1660 escaped_length += 3;
1661 }
1662 // We don't allow strings that are longer than Smi range.
1663 if (!Smi::IsValid(escaped_length)) {
1664 Top::context()->mark_out_of_memory();
1665 return Failure::OutOfMemoryException();
1666 }
1667 }
1668 }
1669 // No length change implies no change. Return original string if no change.
1670 if (escaped_length == length) {
1671 return source;
1672 }
1673 Object* o = Heap::AllocateRawAsciiString(escaped_length);
1674 if (o->IsFailure()) return o;
1675 String* destination = String::cast(o);
1676 int dest_position = 0;
1677
1678 Access<StringInputBuffer> buffer(&string_input_buffer);
1679 buffer->Rewind();
1680 while (buffer->has_more()) {
1681 uint16_t character = buffer->GetNext();
1682 if (character >= 256) {
1683 destination->Set(dest_position, '%');
1684 destination->Set(dest_position+1, 'u');
1685 destination->Set(dest_position+2, hex_chars[character >> 12]);
1686 destination->Set(dest_position+3, hex_chars[(character >> 8) & 0xf]);
1687 destination->Set(dest_position+4, hex_chars[(character >> 4) & 0xf]);
1688 destination->Set(dest_position+5, hex_chars[character & 0xf]);
1689 dest_position += 6;
1690 } else if (IsNotEscaped(character)) {
1691 destination->Set(dest_position, character);
1692 dest_position++;
1693 } else {
1694 destination->Set(dest_position, '%');
1695 destination->Set(dest_position+1, hex_chars[character >> 4]);
1696 destination->Set(dest_position+2, hex_chars[character & 0xf]);
1697 dest_position += 3;
1698 }
1699 }
1700 return destination;
1701}
1702
1703
1704static inline int TwoDigitHex(uint16_t character1, uint16_t character2) {
1705 static const signed char kHexValue['g'] = {
1706 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1707 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1708 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1709 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
1710 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1711 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1712 -1, 10, 11, 12, 13, 14, 15 };
1713
1714 if (character1 > 'f') return -1;
1715 int hi = kHexValue[character1];
1716 if (hi == -1) return -1;
1717 if (character2 > 'f') return -1;
1718 int lo = kHexValue[character2];
1719 if (lo == -1) return -1;
1720 return (hi << 4) + lo;
1721}
1722
1723
1724static inline int Unescape(String* source, int i, int length, int* step) {
1725 uint16_t character = source->Get(i);
1726 int32_t hi, lo;
1727 if (character == '%' &&
1728 i <= length - 6 &&
1729 source->Get(i + 1) == 'u' &&
1730 (hi = TwoDigitHex(source->Get(i + 2), source->Get(i + 3))) != -1 &&
1731 (lo = TwoDigitHex(source->Get(i + 4), source->Get(i + 5))) != -1) {
1732 *step = 6;
1733 return (hi << 8) + lo;
1734 } else if (character == '%' &&
1735 i <= length - 3 &&
1736 (lo = TwoDigitHex(source->Get(i + 1), source->Get(i + 2))) != -1) {
1737 *step = 3;
1738 return lo;
1739 } else {
1740 *step = 1;
1741 return character;
1742 }
1743}
1744
1745
1746static Object* Runtime_URIUnescape(Arguments args) {
1747 NoHandleAllocation ha;
1748 ASSERT(args.length() == 1);
1749 CONVERT_CHECKED(String, source, args[0]);
1750
1751 source->TryFlatten();
1752
1753 bool ascii = true;
1754 int length = source->length();
1755
1756 int unescaped_length = 0;
1757 for (int i = 0; i < length; unescaped_length++) {
1758 int step;
1759 if (Unescape(source, i, length, &step) > String::kMaxAsciiCharCode)
1760 ascii = false;
1761 i += step;
1762 }
1763
1764 // No length change implies no change. Return original string if no change.
1765 if (unescaped_length == length)
1766 return source;
1767
1768 Object* o = ascii ?
1769 Heap::AllocateRawAsciiString(unescaped_length) :
1770 Heap::AllocateRawTwoByteString(unescaped_length);
1771 if (o->IsFailure()) return o;
1772 String* destination = String::cast(o);
1773
1774 int dest_position = 0;
1775 for (int i = 0; i < length; dest_position++) {
1776 int step;
1777 destination->Set(dest_position, Unescape(source, i, length, &step));
1778 i += step;
1779 }
1780 return destination;
1781}
1782
1783
1784static Object* Runtime_StringParseInt(Arguments args) {
1785 NoHandleAllocation ha;
1786
1787 CONVERT_CHECKED(String, s, args[0]);
1788 CONVERT_DOUBLE_CHECKED(n, args[1]);
1789 int radix = FastD2I(n);
1790
1791 s->TryFlatten();
1792
1793 int len = s->length();
1794 int i;
1795
1796 // Skip leading white space.
1797 for (i = 0; i < len && Scanner::kIsWhiteSpace.get(s->Get(i)); i++) ;
1798 if (i == len) return Heap::nan_value();
1799
1800 // Compute the sign (default to +).
1801 int sign = 1;
1802 if (s->Get(i) == '-') {
1803 sign = -1;
1804 i++;
1805 } else if (s->Get(i) == '+') {
1806 i++;
1807 }
1808
1809 // Compute the radix if 0.
1810 if (radix == 0) {
1811 radix = 10;
1812 if (i < len && s->Get(i) == '0') {
1813 radix = 8;
1814 if (i + 1 < len) {
1815 int c = s->Get(i + 1);
1816 if (c == 'x' || c == 'X') {
1817 radix = 16;
1818 i += 2;
1819 }
1820 }
1821 }
1822 } else if (radix == 16) {
1823 // Allow 0x or 0X prefix if radix is 16.
1824 if (i + 1 < len && s->Get(i) == '0') {
1825 int c = s->Get(i + 1);
1826 if (c == 'x' || c == 'X') i += 2;
1827 }
1828 }
1829
1830 RUNTIME_ASSERT(2 <= radix && radix <= 36);
1831 double value;
1832 int end_index = StringToInt(s, i, radix, &value);
1833 if (end_index != i) {
1834 return Heap::NumberFromDouble(sign * value);
1835 }
1836 return Heap::nan_value();
1837}
1838
1839
1840static Object* Runtime_StringParseFloat(Arguments args) {
1841 NoHandleAllocation ha;
1842 CONVERT_CHECKED(String, str, args[0]);
1843
1844 // ECMA-262 section 15.1.2.3, empty string is NaN
1845 double value = StringToDouble(str, ALLOW_TRAILING_JUNK, OS::nan_value());
1846
1847 // Create a number object from the value.
1848 return Heap::NumberFromDouble(value);
1849}
1850
1851
1852static unibrow::Mapping<unibrow::ToUppercase, 128> to_upper_mapping;
1853static unibrow::Mapping<unibrow::ToLowercase, 128> to_lower_mapping;
1854
1855
1856template <class Converter>
1857static Object* ConvertCase(Arguments args,
1858 unibrow::Mapping<Converter, 128> *mapping) {
1859 NoHandleAllocation ha;
1860
1861 CONVERT_CHECKED(String, s, args[0]);
1862 int raw_string_length = s->length();
1863 // Assume that the string is not empty; we need this assumption later
1864 if (raw_string_length == 0) return s;
1865 int length = raw_string_length;
1866
1867 s->TryFlatten();
1868
1869 // We try this twice, once with the assumption that the result is
1870 // no longer than the input and, if that assumption breaks, again
1871 // with the exact length. This is implemented using a goto back
1872 // to this label if we discover that the assumption doesn't hold.
1873 // I apologize sincerely for this and will give a vaffel-is to
1874 // anyone who can implement it in a nicer way.
1875 try_convert:
1876
1877 // Allocate the resulting string.
1878 //
1879 // NOTE: This assumes that the upper/lower case of an ascii
1880 // character is also ascii. This is currently the case, but it
1881 // might break in the future if we implement more context and locale
1882 // dependent upper/lower conversions.
1883 Object* o = s->IsAscii()
1884 ? Heap::AllocateRawAsciiString(length)
1885 : Heap::AllocateRawTwoByteString(length);
1886 if (o->IsFailure())
1887 return o;
1888 String* result = String::cast(o);
1889 bool has_changed_character = false;
1890
1891
1892 // Convert all characters to upper case, assuming that they will fit
1893 // in the buffer
1894 Access<StringInputBuffer> buffer(&string_input_buffer);
1895 buffer->Reset(s);
1896 unibrow::uchar chars[unibrow::kMaxCaseConvertedSize];
1897 int i = 0;
1898 // We can assume that the string is not empty
1899 uc32 current = buffer->GetNext();
1900 while (i < length) {
1901 uc32 next = buffer->has_more() ? buffer->GetNext() : 0;
1902 int char_length = mapping->get(current, next, chars);
1903 if (char_length == 0) {
1904 // The case conversion of this character is the character itself.
1905 result->Set(i, current);
1906 i++;
1907 } else if (char_length == 1) {
1908 // Common case: converting the letter resulted in one character.
1909 ASSERT(static_cast<uc32>(chars[0]) != current);
1910 result->Set(i, chars[0]);
1911 has_changed_character = true;
1912 i++;
1913 } else if (length == raw_string_length) {
1914 // We've assumed that the result would be as long as the
1915 // input but here is a character that converts to several
1916 // characters. No matter, we calculate the exact length
1917 // of the result and try the whole thing again.
1918 //
1919 // Note that this leaves room for optimization. We could just
1920 // memcpy what we already have to the result string. Also,
1921 // the result string is the last object allocated we could
1922 // "realloc" it and probably, in the vast majority of cases,
1923 // extend the existing string to be able to hold the full
1924 // result.
1925 int current_length = i + char_length + mapping->get(next, 0, chars);
1926 while (buffer->has_more()) {
1927 current = buffer->GetNext();
1928 int char_length = mapping->get(current, 0, chars);
1929 if (char_length == 0) char_length = 1;
1930 current += char_length;
1931 }
1932 length = current_length;
1933 goto try_convert;
1934 } else {
1935 for (int j = 0; j < char_length; j++) {
1936 result->Set(i, chars[j]);
1937 i++;
1938 }
1939 has_changed_character = true;
1940 }
1941 current = next;
1942 }
1943 if (has_changed_character) {
1944 return result;
1945 } else {
1946 // If we didn't actually change anything in doing the conversion
1947 // we simple return the result and let the converted string
1948 // become garbage; there is no reason to keep two identical strings
1949 // alive.
1950 return s;
1951 }
1952}
1953
1954
1955static Object* Runtime_StringToLowerCase(Arguments args) {
1956 return ConvertCase<unibrow::ToLowercase>(args, &to_lower_mapping);
1957}
1958
1959
1960static Object* Runtime_StringToUpperCase(Arguments args) {
1961 return ConvertCase<unibrow::ToUppercase>(args, &to_upper_mapping);
1962}
1963
1964
1965static Object* Runtime_ConsStringFst(Arguments args) {
1966 NoHandleAllocation ha;
1967
1968 CONVERT_CHECKED(ConsString, str, args[0]);
1969 return str->first();
1970}
1971
1972
1973static Object* Runtime_ConsStringSnd(Arguments args) {
1974 NoHandleAllocation ha;
1975
1976 CONVERT_CHECKED(ConsString, str, args[0]);
1977 return str->second();
1978}
1979
1980
1981static Object* Runtime_NumberToString(Arguments args) {
1982 NoHandleAllocation ha;
1983 ASSERT(args.length() == 1);
1984
1985 Object* number = args[0];
1986 RUNTIME_ASSERT(number->IsNumber());
1987
1988 Object* cached = Heap::GetNumberStringCache(number);
1989 if (cached != Heap::undefined_value()) {
1990 return cached;
1991 }
1992
1993 char arr[100];
1994 Vector<char> buffer(arr, ARRAY_SIZE(arr));
1995 const char* str;
1996 if (number->IsSmi()) {
1997 int num = Smi::cast(number)->value();
1998 str = IntToCString(num, buffer);
1999 } else {
2000 double num = HeapNumber::cast(number)->value();
2001 str = DoubleToCString(num, buffer);
2002 }
2003 Object* result = Heap::AllocateStringFromAscii(CStrVector(str));
2004
2005 if (!result->IsFailure()) {
2006 Heap::SetNumberStringCache(number, String::cast(result));
2007 }
2008 return result;
2009}
2010
2011
2012static Object* Runtime_NumberToInteger(Arguments args) {
2013 NoHandleAllocation ha;
2014 ASSERT(args.length() == 1);
2015
2016 Object* obj = args[0];
2017
2018 if (obj->IsSmi())
2019 return obj;
2020
2021 CONVERT_DOUBLE_CHECKED(number, obj);
2022 return Heap::NumberFromDouble(DoubleToInteger(number));
2023}
2024
2025
2026static Object* Runtime_NumberToJSUint32(Arguments args) {
2027 NoHandleAllocation ha;
2028 ASSERT(args.length() == 1);
2029
2030 Object* obj = args[0];
2031 if (obj->IsSmi() && Smi::cast(obj)->value() >= 0) return obj;
2032 CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, obj);
2033 return Heap::NumberFromUint32(number);
2034}
2035
2036
2037static Object* Runtime_NumberToJSInt32(Arguments args) {
2038 NoHandleAllocation ha;
2039 ASSERT(args.length() == 1);
2040
2041 Object* obj = args[0];
2042 if (obj->IsSmi()) return obj;
2043 CONVERT_DOUBLE_CHECKED(number, obj);
2044 return Heap::NumberFromInt32(DoubleToInt32(number));
2045}
2046
2047
2048static Object* Runtime_NumberAdd(Arguments args) {
2049 NoHandleAllocation ha;
2050 ASSERT(args.length() == 2);
2051
2052 CONVERT_DOUBLE_CHECKED(x, args[0]);
2053 CONVERT_DOUBLE_CHECKED(y, args[1]);
2054 return Heap::AllocateHeapNumber(x + y);
2055}
2056
2057
2058static Object* Runtime_NumberSub(Arguments args) {
2059 NoHandleAllocation ha;
2060 ASSERT(args.length() == 2);
2061
2062 CONVERT_DOUBLE_CHECKED(x, args[0]);
2063 CONVERT_DOUBLE_CHECKED(y, args[1]);
2064 return Heap::AllocateHeapNumber(x - y);
2065}
2066
2067
2068static Object* Runtime_NumberMul(Arguments args) {
2069 NoHandleAllocation ha;
2070 ASSERT(args.length() == 2);
2071
2072 CONVERT_DOUBLE_CHECKED(x, args[0]);
2073 CONVERT_DOUBLE_CHECKED(y, args[1]);
2074 return Heap::AllocateHeapNumber(x * y);
2075}
2076
2077
2078static Object* Runtime_NumberAlloc(Arguments args) {
2079 NoHandleAllocation ha;
2080 ASSERT(args.length() == 1);
2081 return Heap::AllocateHeapNumber(0);
2082}
2083
2084
2085static Object* Runtime_NumberUnaryMinus(Arguments args) {
2086 NoHandleAllocation ha;
2087 ASSERT(args.length() == 1);
2088
2089 CONVERT_DOUBLE_CHECKED(x, args[0]);
2090 return Heap::AllocateHeapNumber(-x);
2091}
2092
2093
2094static Object* Runtime_NumberDiv(Arguments args) {
2095 NoHandleAllocation ha;
2096 ASSERT(args.length() == 2);
2097
2098 CONVERT_DOUBLE_CHECKED(x, args[0]);
2099 CONVERT_DOUBLE_CHECKED(y, args[1]);
2100 return Heap::NewNumberFromDouble(x / y);
2101}
2102
2103
2104static Object* Runtime_NumberMod(Arguments args) {
2105 NoHandleAllocation ha;
2106 ASSERT(args.length() == 2);
2107
2108 CONVERT_DOUBLE_CHECKED(x, args[0]);
2109 CONVERT_DOUBLE_CHECKED(y, args[1]);
2110
2111#ifdef WIN32
2112 // Workaround MS fmod bugs. ECMA-262 says:
2113 // dividend is finite and divisor is an infinity => result equals dividend
2114 // dividend is a zero and divisor is nonzero finite => result equals dividend
2115 if (!(isfinite(x) && (!isfinite(y) && !isnan(y))) &&
2116 !(x == 0 && (y != 0 && isfinite(y))))
2117#endif
2118 x = fmod(x, y);
2119 // NewNumberFromDouble may return a Smi instead of a Number object
2120 return Heap::NewNumberFromDouble(x);
2121}
2122
2123
2124static Object* Runtime_StringAdd(Arguments args) {
2125 NoHandleAllocation ha;
2126 ASSERT(args.length() == 2);
2127
2128 CONVERT_CHECKED(String, str1, args[0]);
2129 CONVERT_CHECKED(String, str2, args[1]);
2130 int len1 = str1->length();
2131 int len2 = str2->length();
2132 if (len1 == 0) return str2;
2133 if (len2 == 0) return str1;
2134 int length_sum = len1 + len2;
2135 // Make sure that an out of memory exception is thrown if the length
2136 // of the new cons string is too large to fit in a Smi.
2137 if (length_sum > Smi::kMaxValue || length_sum < 0) {
2138 Top::context()->mark_out_of_memory();
2139 return Failure::OutOfMemoryException();
2140 }
2141 return Heap::AllocateConsString(str1, str2);
2142}
2143
2144
2145static Object* Runtime_StringBuilderConcat(Arguments args) {
2146 NoHandleAllocation ha;
2147 ASSERT(args.length() == 2);
2148 CONVERT_CHECKED(JSArray, array, args[0]);
2149 CONVERT_CHECKED(String, special, args[1]);
2150 int special_length = special->length();
2151 Object* smi_array_length = array->length();
2152 if (!smi_array_length->IsSmi()) {
2153 Top::context()->mark_out_of_memory();
2154 return Failure::OutOfMemoryException();
2155 }
2156 int array_length = Smi::cast(smi_array_length)->value();
2157 if (!array->HasFastElements()) {
2158 return Top::Throw(Heap::illegal_argument_symbol());
2159 }
2160 FixedArray* fixed_array = FixedArray::cast(array->elements());
2161 if (fixed_array->length() < array_length)
2162 array_length = fixed_array->length();
2163
2164 if (array_length == 0) {
2165 return Heap::empty_string();
2166 } else if (array_length == 1) {
2167 Object* first = fixed_array->get(0);
2168 if (first->IsString()) return first;
2169 }
2170
2171 bool ascii = special->IsAscii();
2172 int position = 0;
2173 for (int i = 0; i < array_length; i++) {
2174 Object* elt = fixed_array->get(i);
2175 if (elt->IsSmi()) {
2176 int len = Smi::cast(elt)->value();
2177 int pos = len >> 11;
2178 len &= 0x7ff;
2179 if (pos + len > special_length) {
2180 return Top::Throw(Heap::illegal_argument_symbol());
2181 }
2182 position += len;
2183 } else if (elt->IsString()) {
2184 String* element = String::cast(elt);
2185 int element_length = element->length();
2186 if (!Smi::IsValid(element_length + position)) {
2187 Top::context()->mark_out_of_memory();
2188 return Failure::OutOfMemoryException();
2189 }
2190 position += element_length;
2191 if (ascii && !element->IsAscii())
2192 ascii = false;
2193 } else {
2194 return Top::Throw(Heap::illegal_argument_symbol());
2195 }
2196 }
2197
2198 int length = position;
2199 position = 0;
2200 Object* object;
2201 if (ascii) {
2202 object = Heap::AllocateRawAsciiString(length);
2203 } else {
2204 object = Heap::AllocateRawTwoByteString(length);
2205 }
2206 if (object->IsFailure()) return object;
2207
2208 String* answer = String::cast(object);
2209 for (int i = 0; i < array_length; i++) {
2210 Object* element = fixed_array->get(i);
2211 if (element->IsSmi()) {
2212 int len = Smi::cast(element)->value();
2213 int pos = len >> 11;
2214 len &= 0x7ff;
2215 String::Flatten(special, answer, pos, pos + len, position);
2216 position += len;
2217 } else {
2218 String* string = String::cast(element);
2219 int element_length = string->length();
2220 String::Flatten(string, answer, 0, element_length, position);
2221 position += element_length;
2222 }
2223 }
2224 return answer;
2225}
2226
2227
2228static Object* Runtime_NumberOr(Arguments args) {
2229 NoHandleAllocation ha;
2230 ASSERT(args.length() == 2);
2231
2232 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
2233 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
2234 return Heap::NumberFromInt32(x | y);
2235}
2236
2237
2238static Object* Runtime_NumberAnd(Arguments args) {
2239 NoHandleAllocation ha;
2240 ASSERT(args.length() == 2);
2241
2242 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
2243 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
2244 return Heap::NumberFromInt32(x & y);
2245}
2246
2247
2248static Object* Runtime_NumberXor(Arguments args) {
2249 NoHandleAllocation ha;
2250 ASSERT(args.length() == 2);
2251
2252 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
2253 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
2254 return Heap::NumberFromInt32(x ^ y);
2255}
2256
2257
2258static Object* Runtime_NumberNot(Arguments args) {
2259 NoHandleAllocation ha;
2260 ASSERT(args.length() == 1);
2261
2262 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
2263 return Heap::NumberFromInt32(~x);
2264}
2265
2266
2267static Object* Runtime_NumberShl(Arguments args) {
2268 NoHandleAllocation ha;
2269 ASSERT(args.length() == 2);
2270
2271 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
2272 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
2273 return Heap::NumberFromInt32(x << (y & 0x1f));
2274}
2275
2276
2277static Object* Runtime_NumberShr(Arguments args) {
2278 NoHandleAllocation ha;
2279 ASSERT(args.length() == 2);
2280
2281 CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]);
2282 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
2283 return Heap::NumberFromUint32(x >> (y & 0x1f));
2284}
2285
2286
2287static Object* Runtime_NumberSar(Arguments args) {
2288 NoHandleAllocation ha;
2289 ASSERT(args.length() == 2);
2290
2291 CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
2292 CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
2293 return Heap::NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f));
2294}
2295
2296
2297static Object* Runtime_ObjectEquals(Arguments args) {
2298 NoHandleAllocation ha;
2299 ASSERT(args.length() == 2);
2300
2301 return Smi::FromInt(args[0] == args[1] ? EQUAL : NOT_EQUAL);
2302}
2303
2304
2305static Object* Runtime_NumberEquals(Arguments args) {
2306 NoHandleAllocation ha;
2307 ASSERT(args.length() == 2);
2308
2309 CONVERT_DOUBLE_CHECKED(x, args[0]);
2310 CONVERT_DOUBLE_CHECKED(y, args[1]);
2311 if (isnan(x)) return Smi::FromInt(NOT_EQUAL);
2312 if (isnan(y)) return Smi::FromInt(NOT_EQUAL);
2313 if (x == y) return Smi::FromInt(EQUAL);
2314 Object* result;
2315 if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) {
2316 result = Smi::FromInt(EQUAL);
2317 } else {
2318 result = Smi::FromInt(NOT_EQUAL);
2319 }
2320 return result;
2321}
2322
2323
2324static Object* Runtime_StringEquals(Arguments args) {
2325 NoHandleAllocation ha;
2326 ASSERT(args.length() == 2);
2327
2328 CONVERT_CHECKED(String, x, args[0]);
2329 CONVERT_CHECKED(String, y, args[1]);
2330
2331 // This is very similar to String::Equals(String*) but that version
2332 // requires flattened strings as input, whereas we flatten the
2333 // strings only if the fast cases fail. Note that this may fail,
2334 // requiring a GC. String::Equals(String*) returns a bool and has
2335 // no way to signal a failure.
2336 if (y == x) return Smi::FromInt(EQUAL);
2337 if (x->IsSymbol() && y->IsSymbol()) return Smi::FromInt(NOT_EQUAL);
2338 // Compare contents
2339 int len = x->length();
2340 if (len != y->length()) return Smi::FromInt(NOT_EQUAL);
2341 if (len == 0) return Smi::FromInt(EQUAL);
2342 // Fast case: First, middle and last characters.
2343 if (x->Get(0) != y->Get(0)) return Smi::FromInt(NOT_EQUAL);
2344 if (x->Get(len>>1) != y->Get(len>>1)) return Smi::FromInt(NOT_EQUAL);
2345 if (x->Get(len - 1) != y->Get(len - 1)) return Smi::FromInt(NOT_EQUAL);
2346
2347 x->TryFlatten();
2348 y->TryFlatten();
2349
2350 static StringInputBuffer buf1;
2351 static StringInputBuffer buf2;
2352 buf1.Reset(x);
2353 buf2.Reset(y);
2354 while (buf1.has_more()) {
2355 if (buf1.GetNext() != buf2.GetNext())
2356 return Smi::FromInt(NOT_EQUAL);
2357 }
2358 return Smi::FromInt(EQUAL);
2359}
2360
2361
2362static Object* Runtime_NumberCompare(Arguments args) {
2363 NoHandleAllocation ha;
2364 ASSERT(args.length() == 3);
2365
2366 CONVERT_DOUBLE_CHECKED(x, args[0]);
2367 CONVERT_DOUBLE_CHECKED(y, args[1]);
2368 if (isnan(x) || isnan(y)) return args[2];
2369 if (x == y) return Smi::FromInt(EQUAL);
2370 if (isless(x, y)) return Smi::FromInt(LESS);
2371 return Smi::FromInt(GREATER);
2372}
2373
2374
2375static Object* Runtime_StringCompare(Arguments args) {
2376 NoHandleAllocation ha;
2377 ASSERT(args.length() == 2);
2378
2379 CONVERT_CHECKED(String, x, args[0]);
2380 CONVERT_CHECKED(String, y, args[1]);
2381
2382 // A few fast case tests before we flatten.
2383 if (x == y) return Smi::FromInt(EQUAL);
2384 if (y->length() == 0) {
2385 if (x->length() == 0)
2386 return Smi::FromInt(EQUAL);
2387 return Smi::FromInt(GREATER);
2388 } else if (x->length() == 0) {
2389 return Smi::FromInt(LESS);
2390 }
2391 {
2392 int d = x->Get(0) - y->Get(0);
2393 if (d < 0) return Smi::FromInt(LESS);
2394 else if (d > 0) return Smi::FromInt(GREATER);
2395 }
2396
2397 x->TryFlatten();
2398 y->TryFlatten();
2399
2400 static StringInputBuffer bufx;
2401 static StringInputBuffer bufy;
2402 bufx.Reset(x);
2403 bufy.Reset(y);
2404 while (bufx.has_more() && bufy.has_more()) {
2405 int d = bufx.GetNext() - bufy.GetNext();
2406 if (d < 0) return Smi::FromInt(LESS);
2407 else if (d > 0) return Smi::FromInt(GREATER);
2408 }
2409
2410 // x is (non-trivial) prefix of y:
2411 if (bufy.has_more()) return Smi::FromInt(LESS);
2412 // y is prefix of x:
2413 return Smi::FromInt(bufx.has_more() ? GREATER : EQUAL);
2414}
2415
2416
2417static Object* Runtime_Math_abs(Arguments args) {
2418 NoHandleAllocation ha;
2419 ASSERT(args.length() == 1);
2420
2421 CONVERT_DOUBLE_CHECKED(x, args[0]);
2422 return Heap::AllocateHeapNumber(fabs(x));
2423}
2424
2425
2426static Object* Runtime_Math_acos(Arguments args) {
2427 NoHandleAllocation ha;
2428 ASSERT(args.length() == 1);
2429
2430 CONVERT_DOUBLE_CHECKED(x, args[0]);
2431 return Heap::AllocateHeapNumber(acos(x));
2432}
2433
2434
2435static Object* Runtime_Math_asin(Arguments args) {
2436 NoHandleAllocation ha;
2437 ASSERT(args.length() == 1);
2438
2439 CONVERT_DOUBLE_CHECKED(x, args[0]);
2440 return Heap::AllocateHeapNumber(asin(x));
2441}
2442
2443
2444static Object* Runtime_Math_atan(Arguments args) {
2445 NoHandleAllocation ha;
2446 ASSERT(args.length() == 1);
2447
2448 CONVERT_DOUBLE_CHECKED(x, args[0]);
2449 return Heap::AllocateHeapNumber(atan(x));
2450}
2451
2452
2453static Object* Runtime_Math_atan2(Arguments args) {
2454 NoHandleAllocation ha;
2455 ASSERT(args.length() == 2);
2456
2457 CONVERT_DOUBLE_CHECKED(x, args[0]);
2458 CONVERT_DOUBLE_CHECKED(y, args[1]);
2459 double result;
2460 if (isinf(x) && isinf(y)) {
2461 // Make sure that the result in case of two infinite arguments
2462 // is a multiple of Pi / 4. The sign of the result is determined
2463 // by the first argument (x) and the sign of the second argument
2464 // determines the multiplier: one or three.
2465 static double kPiDividedBy4 = 0.78539816339744830962;
2466 int multiplier = (x < 0) ? -1 : 1;
2467 if (y < 0) multiplier *= 3;
2468 result = multiplier * kPiDividedBy4;
2469 } else {
2470 result = atan2(x, y);
2471 }
2472 return Heap::AllocateHeapNumber(result);
2473}
2474
2475
2476static Object* Runtime_Math_ceil(Arguments args) {
2477 NoHandleAllocation ha;
2478 ASSERT(args.length() == 1);
2479
2480 CONVERT_DOUBLE_CHECKED(x, args[0]);
2481 return Heap::NumberFromDouble(ceiling(x));
2482}
2483
2484
2485static Object* Runtime_Math_cos(Arguments args) {
2486 NoHandleAllocation ha;
2487 ASSERT(args.length() == 1);
2488
2489 CONVERT_DOUBLE_CHECKED(x, args[0]);
2490 return Heap::AllocateHeapNumber(cos(x));
2491}
2492
2493
2494static Object* Runtime_Math_exp(Arguments args) {
2495 NoHandleAllocation ha;
2496 ASSERT(args.length() == 1);
2497
2498 CONVERT_DOUBLE_CHECKED(x, args[0]);
2499 return Heap::AllocateHeapNumber(exp(x));
2500}
2501
2502
2503static Object* Runtime_Math_floor(Arguments args) {
2504 NoHandleAllocation ha;
2505 ASSERT(args.length() == 1);
2506
2507 CONVERT_DOUBLE_CHECKED(x, args[0]);
2508 return Heap::NumberFromDouble(floor(x));
2509}
2510
2511
2512static Object* Runtime_Math_log(Arguments args) {
2513 NoHandleAllocation ha;
2514 ASSERT(args.length() == 1);
2515
2516 CONVERT_DOUBLE_CHECKED(x, args[0]);
2517 return Heap::AllocateHeapNumber(log(x));
2518}
2519
2520
2521static Object* Runtime_Math_pow(Arguments args) {
2522 NoHandleAllocation ha;
2523 ASSERT(args.length() == 2);
2524
2525 CONVERT_DOUBLE_CHECKED(x, args[0]);
2526 CONVERT_DOUBLE_CHECKED(y, args[1]);
2527 if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) {
2528 return Heap::nan_value();
2529 } else if (y == 0) {
2530 return Smi::FromInt(1);
2531 } else {
2532 return Heap::AllocateHeapNumber(pow(x, y));
2533 }
2534}
2535
2536// Returns a number value with positive sign, greater than or equal to
2537// 0 but less than 1, chosen randomly.
2538static Object* Runtime_Math_random(Arguments) {
2539 NoHandleAllocation ha;
2540
2541 // To get much better precision, we combine the results of two
2542 // invocations of random(). The result is computed by normalizing a
2543 // double in the range [0, RAND_MAX + 1) obtained by adding the
2544 // high-order bits in the range [0, RAND_MAX] with the low-order
2545 // bits in the range [0, 1).
2546 double lo = static_cast<double>(random()) / (RAND_MAX + 1.0);
2547 double hi = static_cast<double>(random());
2548 double result = (hi + lo) / (RAND_MAX + 1.0);
2549 ASSERT(result >= 0 && result < 1);
2550 return Heap::AllocateHeapNumber(result);
2551}
2552
2553
2554static Object* Runtime_Math_round(Arguments args) {
2555 NoHandleAllocation ha;
2556 ASSERT(args.length() == 1);
2557
2558 CONVERT_DOUBLE_CHECKED(x, args[0]);
2559 if (signbit(x) && x >= -0.5) return Heap::minus_zero_value();
2560 return Heap::NumberFromDouble(floor(x + 0.5));
2561}
2562
2563
2564static Object* Runtime_Math_sin(Arguments args) {
2565 NoHandleAllocation ha;
2566 ASSERT(args.length() == 1);
2567
2568 CONVERT_DOUBLE_CHECKED(x, args[0]);
2569 return Heap::AllocateHeapNumber(sin(x));
2570}
2571
2572
2573static Object* Runtime_Math_sqrt(Arguments args) {
2574 NoHandleAllocation ha;
2575 ASSERT(args.length() == 1);
2576
2577 CONVERT_DOUBLE_CHECKED(x, args[0]);
2578 return Heap::AllocateHeapNumber(sqrt(x));
2579}
2580
2581
2582static Object* Runtime_Math_tan(Arguments args) {
2583 NoHandleAllocation ha;
2584 ASSERT(args.length() == 1);
2585
2586 CONVERT_DOUBLE_CHECKED(x, args[0]);
2587 return Heap::AllocateHeapNumber(tan(x));
2588}
2589
2590
2591static Object* Runtime_NewArguments(Arguments args) {
2592 NoHandleAllocation ha;
2593 ASSERT(args.length() == 1);
2594
2595 // ECMA-262, 3rd., 10.1.8, p.39
2596 CONVERT_CHECKED(JSFunction, callee, args[0]);
2597
2598 // Compute the frame holding the arguments.
2599 JavaScriptFrameIterator it;
2600 it.AdvanceToArgumentsFrame();
2601 JavaScriptFrame* frame = it.frame();
2602
2603 const int length = frame->GetProvidedParametersCount();
2604 Object* result = Heap::AllocateArgumentsObject(callee, length);
2605 if (result->IsFailure()) return result;
2606 FixedArray* array = FixedArray::cast(JSObject::cast(result)->elements());
2607 ASSERT(array->length() == length);
2608 for (int i = 0; i < length; i++) {
2609 array->set(i, frame->GetParameter(i));
2610 }
2611 return result;
2612}
2613
2614
2615static Object* Runtime_NewClosure(Arguments args) {
2616 HandleScope scope;
2617 ASSERT(args.length() == 2);
2618 CONVERT_ARG_CHECKED(JSFunction, boilerplate, 0);
2619 CONVERT_ARG_CHECKED(Context, context, 1);
2620
2621 Handle<JSFunction> result =
2622 Factory::NewFunctionFromBoilerplate(boilerplate, context);
2623 return *result;
2624}
2625
2626
2627static Object* Runtime_NewObject(Arguments args) {
2628 NoHandleAllocation ha;
2629 ASSERT(args.length() == 1);
2630
2631 Object* constructor = args[0];
2632 if (constructor->IsJSFunction()) {
2633 JSFunction* function = JSFunction::cast(constructor);
2634
2635 // Handle steping into constructors.
2636 if (Debug::StepInActive()) {
2637 StackFrameIterator it;
2638 it.Advance();
2639 ASSERT(InternalFrame::cast(it.frame())->is_construct_trampoline());
2640 it.Advance();
2641 if (it.frame()->fp() == Debug::step_in_fp()) {
2642 HandleScope scope;
2643 Debug::FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared()));
2644 }
2645 }
2646
2647 if (function->has_initial_map() &&
2648 function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
2649 // The 'Function' function ignores the receiver object when
2650 // called using 'new' and creates a new JSFunction object that
2651 // is returned. The receiver object is only used for error
2652 // reporting if an error occurs when constructing the new
2653 // JSFunction. AllocateJSObject should not be used to allocate
2654 // JSFunctions since it does not properly initialize the shared
2655 // part of the function. Since the receiver is ignored anyway,
2656 // we use the global object as the receiver instead of a new
2657 // JSFunction object. This way, errors are reported the same
2658 // way whether or not 'Function' is called using 'new'.
2659 return Top::context()->global();
2660 }
2661 return Heap::AllocateJSObject(function);
2662 }
2663
2664 HandleScope scope;
2665 Handle<Object> cons(constructor);
2666 // The constructor is not a function; throw a type error.
2667 Handle<Object> type_error =
2668 Factory::NewTypeError("not_constructor", HandleVector(&cons, 1));
2669 return Top::Throw(*type_error);
2670}
2671
2672
2673#ifdef DEBUG
2674DEFINE_bool(trace_lazy, false, "trace lazy compilation");
2675#endif
2676
2677
2678static Object* Runtime_LazyCompile(Arguments args) {
2679 HandleScope scope;
2680 ASSERT(args.length() == 1);
2681
2682 Handle<JSFunction> function = args.at<JSFunction>(0);
2683#ifdef DEBUG
2684 if (FLAG_trace_lazy) {
2685 PrintF("[lazy: ");
2686 function->shared()->name()->Print();
2687 PrintF("]\n");
2688 }
2689#endif
2690
2691 // Compile the target function.
2692 ASSERT(!function->is_compiled());
2693 if (!CompileLazy(function, KEEP_EXCEPTION)) {
2694 return Failure::Exception();
2695 }
2696
2697 return function->code();
2698}
2699
2700
2701static Object* Runtime_GetCalledFunction(Arguments args) {
2702 HandleScope scope;
2703 ASSERT(args.length() == 1);
2704 StackFrameIterator it;
2705 // Get past the JS-to-C exit frame.
2706 ASSERT(it.frame()->is_exit());
2707 it.Advance();
2708 // Get past the CALL_NON_FUNCTION activation frame.
2709 ASSERT(it.frame()->is_java_script());
2710 it.Advance();
2711 // Argument adaptor frames do not copy the function; we have to skip
2712 // past them to get to the real calling frame.
2713 if (it.frame()->is_arguments_adaptor()) it.Advance();
2714 // Get the function from the top of the expression stack of the
2715 // calling frame.
2716 StandardFrame* frame = StandardFrame::cast(it.frame());
2717 int index = frame->ComputeExpressionsCount() - 1;
2718 Object* result = frame->GetExpression(index);
2719 return result;
2720}
2721
2722
2723static Object* Runtime_GetFunctionDelegate(Arguments args) {
2724 HandleScope scope;
2725 ASSERT(args.length() == 1);
2726 RUNTIME_ASSERT(!args[0]->IsJSFunction());
2727 return *Execution::GetFunctionDelegate(args.at<Object>(0));
2728}
2729
2730
2731static Object* Runtime_NewContext(Arguments args) {
2732 NoHandleAllocation ha;
2733 ASSERT(args.length() == 2);
2734
2735 CONVERT_CHECKED(JSFunction, function, args[1]);
2736 int length = ScopeInfo<>::NumberOfContextSlots(function->code());
2737 Object* result = Heap::AllocateFunctionContext(length, function);
2738 if (result->IsFailure()) return result;
2739
2740 Top::set_context(Context::cast(result));
2741
2742 return args[0]; // return TOS
2743}
2744
2745
2746static Object* Runtime_PushContext(Arguments args) {
2747 NoHandleAllocation ha;
2748 ASSERT(args.length() == 2);
2749
2750 // Convert the object to a proper JavaScript object.
2751 Object* object = args[1];
2752 if (!object->IsJSObject()) {
2753 object = object->ToObject();
2754 if (object->IsFailure()) {
2755 if (!Failure::cast(object)->IsInternalError()) return object;
2756 HandleScope scope;
2757 Handle<Object> handle(args[1]);
2758 Handle<Object> result =
2759 Factory::NewTypeError("with_expression", HandleVector(&handle, 1));
2760 return Top::Throw(*result);
2761 }
2762 }
2763
2764 Object* result =
2765 Heap::AllocateWithContext(Top::context(), JSObject::cast(object));
2766 if (result->IsFailure()) return result;
2767
2768 Top::set_context(Context::cast(result));
2769
2770 return args[0]; // return TOS
2771}
2772
2773
2774static Object* Runtime_LookupContext(Arguments args) {
2775 HandleScope scope;
2776 ASSERT(args.length() == 2);
2777
2778 CONVERT_ARG_CHECKED(Context, context, 0);
2779 CONVERT_ARG_CHECKED(String, name, 1);
2780
2781 int index;
2782 PropertyAttributes attributes;
2783 ContextLookupFlags flags = FOLLOW_CHAINS;
2784 Handle<Object> context_obj =
2785 context->Lookup(name, flags, &index, &attributes);
2786
2787 if (index < 0 && *context_obj != NULL) {
2788 ASSERT(context_obj->IsJSObject());
2789 return *context_obj;
2790 }
2791
2792 // No intermediate context found. Use global object by default.
2793 return Top::context()->global();
2794}
2795
2796
2797
2798
2799// A mechanism to return pairs of Object*'s. This is somewhat
2800// compiler-dependent as it assumes that a 64-bit value (a long long)
2801// is returned via two registers (edx:eax on ia32). Both the ia32 and
2802// arm platform support this; it is mostly an issue of "coaxing" the
2803// compiler to do the right thing.
2804//
2805// TODO(1236026): This is a non-portable hack that should be removed.
2806typedef uint64_t ObjPair;
2807ObjPair MakePair(Object* x, Object* y) {
2808 return reinterpret_cast<uint32_t>(x) |
2809 (reinterpret_cast<ObjPair>(y) << 32);
2810}
2811
2812
2813static Object* Unhole(Object* x, PropertyAttributes attributes) {
2814 ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0);
2815 USE(attributes);
2816 return x->IsTheHole() ? Heap::undefined_value() : x;
2817}
2818
2819
2820static ObjPair LoadContextSlotHelper(Arguments args, bool throw_error) {
2821 HandleScope scope;
2822 ASSERT(args.length() == 2);
2823
2824 if (!args[0]->IsContext()) return MakePair(IllegalOperation(), NULL);
2825 Handle<Context> context = args.at<Context>(0);
2826 Handle<String> name(String::cast(args[1]));
2827
2828 int index;
2829 PropertyAttributes attributes;
2830 ContextLookupFlags flags = FOLLOW_CHAINS;
2831 Handle<Object> context_obj =
2832 context->Lookup(name, flags, &index, &attributes);
2833
2834 if (index >= 0) {
2835 if (context_obj->IsContext()) {
2836 // The context is an Execution context, and the "property" we were looking
2837 // for is a local variable in that context. According to ECMA-262, 3rd.,
2838 // 10.1.6 and 10.2.3, the receiver is the global object.
2839 return MakePair(
2840 Unhole(Handle<Context>::cast(context_obj)->get(index), attributes),
2841 Top::context()->global());
2842 } else {
2843 return MakePair(
2844 Unhole(Handle<JSObject>::cast(context_obj)->GetElement(index),
2845 attributes),
2846 *context_obj);
2847 }
2848 }
2849
2850 if (*context_obj != NULL) {
2851 ASSERT(Handle<JSObject>::cast(context_obj)->HasProperty(*name));
2852 // Note: As of 5/29/2008, GetProperty does the "unholing" and so this call
2853 // here is redundant. We left it anyway, to be explicit; also it's not clear
2854 // why GetProperty should do the unholing in the first place.
2855 return MakePair(
2856 Unhole(Handle<JSObject>::cast(context_obj)->GetProperty(*name),
2857 attributes),
2858 *context_obj);
2859 }
2860
2861 if (throw_error) {
2862 // The property doesn't exist - throw exception.
2863 Handle<Object> reference_error =
2864 Factory::NewReferenceError("not_defined", HandleVector(&name, 1));
2865 return MakePair(Top::Throw(*reference_error), NULL);
2866 } else {
2867 // The property doesn't exist - return undefined
2868 return MakePair(Heap::undefined_value(), Heap::undefined_value());
2869 }
2870}
2871
2872
2873static ObjPair Runtime_LoadContextSlot(Arguments args) {
2874 return LoadContextSlotHelper(args, true);
2875}
2876
2877
2878static ObjPair Runtime_LoadContextSlotNoReferenceError(Arguments args) {
2879 return LoadContextSlotHelper(args, false);
2880}
2881
2882
2883static Object* Runtime_StoreContextSlot(Arguments args) {
2884 HandleScope scope;
2885 ASSERT(args.length() == 3);
2886
2887 Handle<Object> value(args[0]);
2888 CONVERT_ARG_CHECKED(Context, context, 1);
2889 Handle<String> name(String::cast(args[2]));
2890
2891 int index;
2892 PropertyAttributes attributes;
2893 ContextLookupFlags flags = FOLLOW_CHAINS;
2894 Handle<Object> context_obj =
2895 context->Lookup(name, flags, &index, &attributes);
2896
2897 if (index >= 0) {
2898 if (context_obj->IsContext()) {
2899 // Ignore if read_only variable.
2900 if ((attributes & READ_ONLY) == 0) {
2901 Handle<Context>::cast(context_obj)->set(index, *value);
2902 }
2903 } else {
2904 ASSERT((attributes & READ_ONLY) == 0);
2905 Object* result =
2906 Handle<JSObject>::cast(context_obj)->SetElement(index, *value);
2907 USE(result);
2908 ASSERT(!result->IsFailure());
2909 }
2910 return *value;
2911 }
2912
2913 // Slow case: The property is not in a FixedArray context.
2914 // It is either in an JSObject extension context or it was not found.
2915 Handle<JSObject> context_ext;
2916
2917 if (*context_obj != NULL) {
2918 // The property exists in the extension context.
2919 context_ext = Handle<JSObject>::cast(context_obj);
2920 } else {
2921 // The property was not found. It needs to be stored in the global context.
2922 ASSERT(attributes == ABSENT);
2923 attributes = NONE;
2924 context_ext = Handle<JSObject>(Top::context()->global());
2925 }
2926
2927 // Set the property, but ignore if read_only variable.
2928 if ((attributes & READ_ONLY) == 0) {
2929 Handle<Object> set = SetProperty(context_ext, name, value, attributes);
2930 if (set.is_null()) {
2931 // Failure::Exception is converted to a null handle in the
2932 // handle-based methods such as SetProperty. We therefore need
2933 // to convert null handles back to exceptions.
2934 ASSERT(Top::has_pending_exception());
2935 return Failure::Exception();
2936 }
2937 }
2938 return *value;
2939}
2940
2941
2942static Object* Runtime_Throw(Arguments args) {
2943 HandleScope scope;
2944 ASSERT(args.length() == 1);
2945
2946 return Top::Throw(args[0]);
2947}
2948
2949
2950static Object* Runtime_ReThrow(Arguments args) {
2951 HandleScope scope;
2952 ASSERT(args.length() == 1);
2953
2954 return Top::ReThrow(args[0]);
2955}
2956
2957
2958static Object* Runtime_ThrowReferenceError(Arguments args) {
2959 HandleScope scope;
2960 ASSERT(args.length() == 1);
2961
2962 Handle<Object> name(args[0]);
2963 Handle<Object> reference_error =
2964 Factory::NewReferenceError("not_defined", HandleVector(&name, 1));
2965 return Top::Throw(*reference_error);
2966}
2967
2968
2969static Object* Runtime_StackOverflow(Arguments args) {
2970 NoHandleAllocation na;
2971 return Top::StackOverflow();
2972}
2973
2974
2975static Object* RuntimePreempt(Arguments args) {
2976 // Clear the preempt request flag.
2977 StackGuard::Continue(PREEMPT);
2978
2979 ContextSwitcher::PreemptionReceived();
2980
2981 {
2982 v8::Unlocker unlocker;
2983 Thread::YieldCPU();
2984 }
2985
2986 return Heap::undefined_value();
2987}
2988
2989
2990static Object* Runtime_DebugBreak(Arguments args) {
kasper.lund44510672008-07-25 07:37:58 +00002991 // Just continue if breaks are disabled or if we fail to load the debugger.
2992 if (Debug::disable_break() || !Debug::Load()) {
kasper.lundbd3ec4e2008-07-09 11:06:54 +00002993 return args[0];
2994 }
2995
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002996 // Don't break in system functions. If the current function is either in the
2997 // builtins object of some context or is in the debug context just return with
2998 // the debug break stack guard active.
2999 JavaScriptFrameIterator it;
3000 JavaScriptFrame* frame = it.frame();
3001 Object* fun = frame->function();
3002 if (fun->IsJSFunction()) {
3003 GlobalObject* global = JSFunction::cast(fun)->context()->global();
3004 if (global->IsJSBuiltinsObject() || Debug::IsDebugGlobal(global)) {
3005 return args[0];
3006 }
3007 }
3008
3009 // Clear the debug request flag.
3010 StackGuard::Continue(DEBUGBREAK);
3011
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003012 HandleScope scope;
3013 SaveBreakFrame save;
3014 EnterDebuggerContext enter;
3015
3016 // Process debug requests. Returns true if break request.
3017 bool break_request = Debugger::ProcessPendingRequests();
3018
3019 // Notify the debug event listeners if break request.
3020 if (break_request) {
3021 Debugger::OnDebugBreak(Factory::undefined_value());
3022 }
3023
3024 // Return to continue execution.
3025 return args[0];
3026}
3027
3028
3029static Object* Runtime_StackGuard(Arguments args) {
3030 ASSERT(args.length() == 1);
3031
3032 // First check if this is a real stack overflow.
3033 if (StackGuard::IsStackOverflow()) return Runtime_StackOverflow(args);
3034
3035 // If not real stack overflow the stack guard was used to interrupt
3036 // execution for another purpose.
3037 if (StackGuard::IsDebugBreak()) Runtime_DebugBreak(args);
3038 if (StackGuard::IsPreempted()) RuntimePreempt(args);
3039 if (StackGuard::IsInterrupted()) {
3040 // interrupt
3041 StackGuard::Continue(INTERRUPT);
3042 return Top::StackOverflow();
3043 }
3044 return Heap::undefined_value();
3045}
3046
3047
3048// NOTE: These PrintXXX functions are defined for all builds (not just
3049// DEBUG builds) because we may want to be able to trace function
3050// calls in all modes.
3051static void PrintString(String* str) {
3052 // not uncommon to have empty strings
3053 if (str->length() > 0) {
3054 SmartPointer<char> s =
3055 str->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
3056 PrintF("%s", *s);
3057 }
3058}
3059
3060
3061static void PrintObject(Object* obj) {
3062 if (obj->IsSmi()) {
3063 PrintF("%d", Smi::cast(obj)->value());
3064 } else if (obj->IsString() || obj->IsSymbol()) {
3065 PrintString(String::cast(obj));
3066 } else if (obj->IsNumber()) {
3067 PrintF("%g", obj->Number());
3068 } else if (obj->IsFailure()) {
3069 PrintF("<failure>");
3070 } else if (obj->IsUndefined()) {
3071 PrintF("<undefined>");
3072 } else if (obj->IsNull()) {
3073 PrintF("<null>");
3074 } else if (obj->IsTrue()) {
3075 PrintF("<true>");
3076 } else if (obj->IsFalse()) {
3077 PrintF("<false>");
3078 } else {
3079 PrintF("%p", obj);
3080 }
3081}
3082
3083
3084static int StackSize() {
3085 int n = 0;
3086 for (JavaScriptFrameIterator it; !it.done(); it.Advance()) n++;
3087 return n;
3088}
3089
3090
3091static void PrintTransition(Object* result) {
3092 // indentation
3093 { const int nmax = 80;
3094 int n = StackSize();
3095 if (n <= nmax)
3096 PrintF("%4d:%*s", n, n, "");
3097 else
3098 PrintF("%4d:%*s", n, nmax, "...");
3099 }
3100
3101 if (result == NULL) {
3102 // constructor calls
3103 JavaScriptFrameIterator it;
3104 JavaScriptFrame* frame = it.frame();
3105 if (frame->IsConstructor()) PrintF("new ");
3106 // function name
3107 Object* fun = frame->function();
3108 if (fun->IsJSFunction()) {
3109 PrintObject(JSFunction::cast(fun)->shared()->name());
3110 } else {
3111 PrintObject(fun);
3112 }
3113 // function arguments
3114 // (we are intentionally only printing the actually
3115 // supplied parameters, not all parameters required)
3116 PrintF("(this=");
3117 PrintObject(frame->receiver());
3118 const int length = frame->GetProvidedParametersCount();
3119 for (int i = 0; i < length; i++) {
3120 PrintF(", ");
3121 PrintObject(frame->GetParameter(i));
3122 }
3123 PrintF(") {\n");
3124
3125 } else {
3126 // function result
3127 PrintF("} -> ");
3128 PrintObject(result);
3129 PrintF("\n");
3130 }
3131}
3132
3133
3134static Object* Runtime_TraceEnter(Arguments args) {
3135 NoHandleAllocation ha;
3136 PrintTransition(NULL);
3137 return args[0]; // return TOS
3138}
3139
3140
3141static Object* Runtime_TraceExit(Arguments args) {
3142 NoHandleAllocation ha;
3143 PrintTransition(args[0]);
3144 return args[0]; // return TOS
3145}
3146
3147
3148static Object* Runtime_DebugPrint(Arguments args) {
3149 NoHandleAllocation ha;
3150 ASSERT(args.length() == 1);
3151
3152#ifdef DEBUG
3153 if (args[0]->IsString()) {
3154 // If we have a string, assume it's a code "marker"
3155 // and print some interesting cpu debugging info.
3156 JavaScriptFrameIterator it;
3157 JavaScriptFrame* frame = it.frame();
3158 PrintF("fp = %p, sp = %p, pp = %p: ",
3159 frame->fp(), frame->sp(), frame->pp());
3160 } else {
3161 PrintF("DebugPrint: ");
3162 }
3163 args[0]->Print();
3164#else
3165 PrintF("DebugPrint: %p", args[0]);
3166#endif
3167 PrintF("\n");
3168
3169 return args[0]; // return TOS
3170}
3171
3172
3173static Object* Runtime_DebugTrace(Arguments args) {
3174 ASSERT(args.length() == 1);
3175 NoHandleAllocation ha;
3176 Top::PrintStack();
3177 return args[0]; // return TOS
3178}
3179
3180
3181static Object* Runtime_DateCurrentTime(Arguments) {
3182 NoHandleAllocation ha;
3183
3184 // According to ECMA-262, section 15.9.1, page 117, the precision of
3185 // the number in a Date object representing a particular instant in
3186 // time is milliseconds. Therefore, we floor the result of getting
3187 // the OS time.
3188 double millis = floor(OS::TimeCurrentMillis());
3189 return Heap::NumberFromDouble(millis);
3190}
3191
3192
3193static Object* Runtime_DateParseString(Arguments args) {
3194 HandleScope scope;
3195 ASSERT(args.length() == 1);
3196
3197 CONVERT_CHECKED(String, string_object, args[0]);
3198
3199 Handle<String> str(string_object);
3200 Handle<FixedArray> output = Factory::NewFixedArray(DateParser::OUTPUT_SIZE);
3201 if (DateParser::Parse(*str, *output)) {
3202 return *Factory::NewJSArrayWithElements(output);
3203 } else {
3204 return *Factory::null_value();
3205 }
3206}
3207
3208
3209static Object* Runtime_DateLocalTimezone(Arguments args) {
3210 NoHandleAllocation ha;
3211 ASSERT(args.length() == 1);
3212
3213 CONVERT_DOUBLE_CHECKED(x, args[0]);
3214 char* zone = OS::LocalTimezone(x);
3215 return Heap::AllocateStringFromUtf8(CStrVector(zone));
3216}
3217
3218
3219static Object* Runtime_DateLocalTimeOffset(Arguments args) {
3220 NoHandleAllocation ha;
3221 ASSERT(args.length() == 1);
3222
3223 return Heap::NumberFromDouble(OS::LocalTimeOffset());
3224}
3225
3226
3227static Object* Runtime_DateDaylightSavingsOffset(Arguments args) {
3228 NoHandleAllocation ha;
3229 ASSERT(args.length() == 1);
3230
3231 CONVERT_DOUBLE_CHECKED(x, args[0]);
3232 return Heap::NumberFromDouble(OS::DaylightSavingsOffset(x));
3233}
3234
3235
3236
3237static Object* Runtime_NumberIsNaN(Arguments args) {
3238 NoHandleAllocation ha;
3239 ASSERT(args.length() == 1);
3240
3241 CONVERT_DOUBLE_CHECKED(value, args[0]);
3242 if (isnan(value)) {
3243 return Heap::true_value();
3244 } else {
3245 return Heap::false_value();
3246 }
3247}
3248
3249
3250static Object* Runtime_NumberIsFinite(Arguments args) {
3251 NoHandleAllocation ha;
3252 ASSERT(args.length() == 1);
3253
3254 CONVERT_DOUBLE_CHECKED(value, args[0]);
3255 Object* result;
3256 if (isnan(value) || (fpclassify(value) == FP_INFINITE)) {
3257 result = Heap::false_value();
3258 } else {
3259 result = Heap::true_value();
3260 }
3261 return result;
3262}
3263
3264
3265static Object* Runtime_NumberMaxValue(Arguments) {
3266 NoHandleAllocation ha;
3267
3268 return Heap::number_max_value();
3269}
3270
3271
3272static Object* Runtime_NumberMinValue(Arguments) {
3273 NoHandleAllocation ha;
3274
3275 return Heap::number_min_value();
3276}
3277
3278
3279static Object* Runtime_NumberNaN(Arguments) {
3280 NoHandleAllocation ha;
3281
3282 return Heap::nan_value();
3283}
3284
3285
3286static Object* Runtime_NumberNegativeInfinity(Arguments) {
3287 NoHandleAllocation ha;
3288
3289 return Heap::negative_infinity_value();
3290}
3291
3292
3293static Object* Runtime_NumberPositiveInfinity(Arguments) {
3294 NoHandleAllocation ha;
3295
3296 return Heap::infinity_value();
3297}
3298
3299
3300static Object* EvalContext() {
3301 // The topmost JS frame belongs to the eval function which called
3302 // the CompileString runtime function. We need to unwind one level
3303 // to get to the caller of eval.
3304 StackFrameLocator locator;
3305 JavaScriptFrame* frame = locator.FindJavaScriptFrame(1);
3306
kasper.lund44510672008-07-25 07:37:58 +00003307 // TODO(900055): Right now we check if the caller of eval() supports
3308 // eval to determine if it's an aliased eval or not. This may not be
3309 // entirely correct in the unlikely case where a function uses both
3310 // aliased and direct eval calls.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003311 HandleScope scope;
3312 if (!ScopeInfo<>::SupportsEval(frame->FindCode())) {
kasper.lund44510672008-07-25 07:37:58 +00003313 // Aliased eval: Evaluate in the global context of the eval
3314 // function to support aliased, cross environment evals.
3315 return *Top::global_context();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00003316 }
3317
3318 // Fetch the caller context from the frame.
3319 Handle<Context> caller(Context::cast(frame->context()));
3320
3321 // Check for eval() invocations that cross environments. Use the
3322 // context from the stack if evaluating in current environment.
3323 Handle<Context> target = Top::global_context();
3324 if (caller->global_context() == *target) return *caller;
3325
3326 // Compute a function closure that captures the calling context. We
3327 // need a function that has trivial scope info, since it is only
3328 // used to hold the context chain together.
3329 Handle<JSFunction> closure = Factory::NewFunction(Factory::empty_symbol(),
3330 Factory::undefined_value());
3331 closure->set_context(*caller);
3332
3333 // Create a new adaptor context that has the target environment as
3334 // the extension object. This enables the evaluated code to see both
3335 // the current context with locals and everything and to see global
3336 // variables declared in the target global object. Furthermore, any
3337 // properties introduced with 'var' will be added to the target
3338 // global object because it is the extension object.
3339 Handle<Context> adaptor =
3340 Factory::NewFunctionContext(Context::MIN_CONTEXT_SLOTS, closure);
3341 adaptor->set_extension(target->global());
3342 return *adaptor;
3343}
3344
3345
3346static Object* Runtime_EvalReceiver(Arguments args) {
3347 StackFrameLocator locator;
3348 return locator.FindJavaScriptFrame(1)->receiver();
3349}
3350
3351
3352static Object* Runtime_CompileString(Arguments args) {
3353 HandleScope scope;
3354 ASSERT(args.length() == 2);
3355 bool contextual = args[1]->IsTrue();
3356 RUNTIME_ASSERT(contextual || args[1]->IsFalse());
3357
3358 // Compute the eval context.
3359 Handle<Context> context;
3360 if (contextual) {
3361 // Get eval context. May not be available if we are calling eval
3362 // through an alias, and the corresponding frame doesn't have a
3363 // proper eval context set up.
3364 Object* eval_context = EvalContext();
3365 if (eval_context->IsFailure()) return eval_context;
3366 context = Handle<Context>(Context::cast(eval_context));
3367 } else {
3368 context = Handle<Context>(Top::context()->global_context());
3369 }
3370
3371 // Compile eval() source.
3372 Handle<String> source(String::cast(args[0]));
3373 Handle<JSFunction> boilerplate =
3374 Compiler::CompileEval(context->IsGlobalContext(), source);
3375 if (boilerplate.is_null()) return Failure::Exception();
3376 Handle<JSFunction> fun =
3377 Factory::NewFunctionFromBoilerplate(boilerplate, context);
3378 return *fun;
3379}
3380
3381
3382static Object* Runtime_CompileScript(Arguments args) {
3383 HandleScope scope;
3384 ASSERT(args.length() == 4);
3385
3386 CONVERT_ARG_CHECKED(String, source, 0);
3387 CONVERT_ARG_CHECKED(String, script, 1);
3388 CONVERT_CHECKED(Smi, line_attrs, args[2]);
3389 int line = line_attrs->value();
3390 CONVERT_CHECKED(Smi, col_attrs, args[3]);
3391 int col = col_attrs->value();
3392 Handle<JSFunction> boilerplate =
3393 Compiler::Compile(source, script, line, col, NULL, NULL);
3394 if (boilerplate.is_null()) return Failure::Exception();
3395 Handle<JSFunction> fun =
3396 Factory::NewFunctionFromBoilerplate(boilerplate,
3397 Handle<Context>(Top::context()));
3398 return *fun;
3399}
3400
3401
3402static Object* Runtime_SetNewFunctionAttributes(Arguments args) {
3403 // This utility adjusts the property attributes for newly created Function
3404 // object ("new Function(...)") by changing the map.
3405 // All it does is changing the prototype property to enumerable
3406 // as specified in ECMA262, 15.3.5.2.
3407 HandleScope scope;
3408 ASSERT(args.length() == 1);
3409 CONVERT_ARG_CHECKED(JSFunction, func, 0);
3410 ASSERT(func->map()->instance_type() ==
3411 Top::function_instance_map()->instance_type());
3412 ASSERT(func->map()->instance_size() ==
3413 Top::function_instance_map()->instance_size());
3414 func->set_map(*Top::function_instance_map());
3415 return *func;
3416}
3417
3418
3419// This will not allocate (flatten the string), but it may run
3420// very slowly for very deeply nested ConsStrings. For debugging use only.
3421static Object* Runtime_GlobalPrint(Arguments args) {
3422 NoHandleAllocation ha;
3423 ASSERT(args.length() == 1);
3424
3425 CONVERT_CHECKED(String, string, args[0]);
3426 StringInputBuffer buffer(string);
3427 while (buffer.has_more()) {
3428 uint16_t character = buffer.GetNext();
3429 PrintF("%c", character);
3430 }
3431 return string;
3432}
3433
3434
3435static Object* Runtime_RemoveArrayHoles(Arguments args) {
3436 ASSERT(args.length() == 1);
3437 // Ignore the case if this is not a JSArray.
3438 if (!args[0]->IsJSArray()) return args[0];
3439 return JSArray::cast(args[0])->RemoveHoles();
3440}
3441
3442
3443// Move contents of argument 0 (an array) to argument 1 (an array)
3444static Object* Runtime_MoveArrayContents(Arguments args) {
3445 ASSERT(args.length() == 2);
3446 CONVERT_CHECKED(JSArray, from, args[0]);
3447 CONVERT_CHECKED(JSArray, to, args[1]);
3448 to->SetContent(FixedArray::cast(from->elements()));
3449 to->set_length(from->length());
3450 from->SetContent(Heap::empty_fixed_array());
3451 from->set_length(0);
3452 return to;
3453}
3454
3455
3456// How many elements does this array have?
3457static Object* Runtime_EstimateNumberOfElements(Arguments args) {
3458 ASSERT(args.length() == 1);
3459 CONVERT_CHECKED(JSArray, array, args[0]);
3460 HeapObject* elements = array->elements();
3461 if (elements->IsDictionary()) {
3462 return Smi::FromInt(Dictionary::cast(elements)->NumberOfElements());
3463 } else {
3464 return array->length();
3465 }
3466}
3467
3468
3469// Returns an array that tells you where in the [0, length) interval an array
3470// might have elements. Can either return keys or intervals. Keys can have
3471// gaps in (undefined). Intervals can also span over some undefined keys.
3472static Object* Runtime_GetArrayKeys(Arguments args) {
3473 ASSERT(args.length() == 2);
3474 HandleScope scope;
3475 CONVERT_CHECKED(JSArray, raw_array, args[0]);
3476 Handle<JSArray> array(raw_array);
3477 CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
3478 HeapObject* elements = array->elements();
3479 if (elements->IsDictionary()) {
3480 // Create an array and get all the keys into it, then remove all the
3481 // keys that are not integers in the range 0 to length-1.
3482 Handle<FixedArray> keys = GetKeysInFixedArrayFor(array);
3483 int keys_length = keys->length();
3484 for (int i = 0; i < keys_length; i++) {
3485 Object* key = keys->get(i);
3486 uint32_t index;
3487 if (!Array::IndexFromObject(key, &index) || index >= length) {
3488 // Zap invalid keys.
3489 keys->set_undefined(i);
3490 }
3491 }
3492 return *Factory::NewJSArrayWithElements(keys);
3493 } else {
3494 Handle<FixedArray> single_interval = Factory::NewFixedArray(2);
3495 // -1 means start of array.
3496 single_interval->set(0, Smi::FromInt(-1));
3497 Handle<Object> length_object =
3498 Factory::NewNumber(static_cast<double>(length));
3499 single_interval->set(1, *length_object);
3500 return *Factory::NewJSArrayWithElements(single_interval);
3501 }
3502}
3503
3504
3505// DefineAccessor takes an optional final argument which is the
3506// property attributes (eg, DONT_ENUM, DONT_DELETE). IMPORTANT: due
3507// to the way accessors are implemented, it is set for both the getter
3508// and setter on the first call to DefineAccessor and ignored on
3509// subsequent calls.
3510static Object* Runtime_DefineAccessor(Arguments args) {
3511 RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
3512 // Compute attributes.
3513 PropertyAttributes attributes = NONE;
3514 if (args.length() == 5) {
3515 CONVERT_CHECKED(Smi, attrs, args[4]);
3516 int value = attrs->value();
3517 // Only attribute bits should be set.
3518 ASSERT((value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
3519 attributes = static_cast<PropertyAttributes>(value);
3520 }
3521
3522 CONVERT_CHECKED(JSObject, obj, args[0]);
3523 CONVERT_CHECKED(String, name, args[1]);
3524 CONVERT_CHECKED(Smi, flag, args[2]);
3525 CONVERT_CHECKED(JSFunction, fun, args[3]);
3526 return obj->DefineAccessor(name, flag->value() == 0, fun, attributes);
3527}
3528
3529
3530static Object* Runtime_LookupAccessor(Arguments args) {
3531 ASSERT(args.length() == 3);
3532 CONVERT_CHECKED(JSObject, obj, args[0]);
3533 CONVERT_CHECKED(String, name, args[1]);
3534 CONVERT_CHECKED(Smi, flag, args[2]);
3535 return obj->LookupAccessor(name, flag->value() == 0);
3536}
3537
3538
3539// Helper functions for wrapping and unwrapping stack frame ids.
3540static Smi* WrapFrameId(StackFrame::Id id) {
3541 ASSERT(IsAligned(OffsetFrom(id), 4));
3542 return Smi::FromInt(id >> 2);
3543}
3544
3545
3546static StackFrame::Id UnwrapFrameId(Smi* wrapped) {
3547 return static_cast<StackFrame::Id>(wrapped->value() << 2);
3548}
3549
3550
3551// Adds a JavaScript function as a debug event listener.
3552// args[0]: debug event listener function
3553// args[1]: object supplied during callback
3554static Object* Runtime_AddDebugEventListener(Arguments args) {
3555 ASSERT(args.length() == 2);
3556 // Convert the parameters to API objects to call the API function for adding
3557 // a JavaScript function as debug event listener.
3558 CONVERT_ARG_CHECKED(JSFunction, raw_fun, 0);
3559 v8::Handle<v8::Function> fun(ToApi<v8::Function>(raw_fun));
3560 v8::Handle<v8::Value> data(ToApi<v8::Value>(args.at<Object>(0)));
3561 v8::Debug::AddDebugEventListener(fun, data);
3562
3563 return Heap::undefined_value();
3564}
3565
3566
3567// Removes a JavaScript function debug event listener.
3568// args[0]: debug event listener function
3569static Object* Runtime_RemoveDebugEventListener(Arguments args) {
3570 ASSERT(args.length() == 1);
3571 // Convert the parameter to an API object to call the API function for
3572 // removing a JavaScript function debug event listener.
3573 CONVERT_ARG_CHECKED(JSFunction, raw_fun, 0);
3574 v8::Handle<v8::Function> fun(ToApi<v8::Function>(raw_fun));
3575 v8::Debug::RemoveDebugEventListener(fun);
3576
3577 return Heap::undefined_value();
3578}
3579
3580
3581static Object* Runtime_Break(Arguments args) {
3582 ASSERT(args.length() == 1);
3583 StackGuard::DebugBreak();
3584 return Heap::undefined_value();
3585}
3586
3587
3588static Object* DebugLookupResultValue(LookupResult* result) {
3589 Object* value;
3590 switch (result->type()) {
3591 case NORMAL: {
3592 Dictionary* dict =
3593 JSObject::cast(result->holder())->property_dictionary();
3594 value = dict->ValueAt(result->GetDictionaryEntry());
3595 if (value->IsTheHole()) {
3596 return Heap::undefined_value();
3597 }
3598 return value;
3599 }
3600 case FIELD:
3601 value =
3602 JSObject::cast(
3603 result->holder())->properties()->get(result->GetFieldIndex());
3604 if (value->IsTheHole()) {
3605 return Heap::undefined_value();
3606 }
3607 return value;
3608 case CONSTANT_FUNCTION:
3609 return result->GetConstantFunction();
3610 case CALLBACKS:
3611 return Heap::undefined_value();
3612 case MAP_TRANSITION:
3613 return Heap::undefined_value();
3614 case INTERCEPTOR:
3615 return Heap::undefined_value();
3616 default:
3617 UNREACHABLE();
3618 }
3619 return Heap::undefined_value();
3620}
3621
3622
3623static Object* Runtime_DebugGetLocalPropertyDetails(Arguments args) {
3624 HandleScope scope;
3625
3626 ASSERT(args.length() == 2);
3627
3628 CONVERT_ARG_CHECKED(JSObject, obj, 0);
3629 CONVERT_ARG_CHECKED(String, name, 1);
3630
3631 // Check if the name is trivially convertible to an index and get the element
3632 // if so.
3633 uint32_t index;
3634 if (name->AsArrayIndex(&index)) {
3635 Handle<FixedArray> details = Factory::NewFixedArray(2);
3636 details->set(0, Runtime::GetElementOrCharAt(obj, index));
3637 details->set(1, PropertyDetails(NONE, NORMAL).AsSmi());
3638 return *Factory::NewJSArrayWithElements(details);
3639 }
3640
3641 // Perform standard local lookup on the object.
3642 LookupResult result;
3643 obj->LocalLookup(*name, &result);
3644 if (result.IsProperty()) {
3645 Handle<Object> value(DebugLookupResultValue(&result));
3646 Handle<FixedArray> details = Factory::NewFixedArray(2);
3647 details->set(0, *value);
3648 details->set(1, result.GetPropertyDetails().AsSmi());
3649 return *Factory::NewJSArrayWithElements(details);
3650 }
3651 return Heap::undefined_value();
3652}
3653
3654
3655static Object* Runtime_DebugGetProperty(Arguments args) {
3656 HandleScope scope;
3657
3658 ASSERT(args.length() == 2);
3659
3660 CONVERT_ARG_CHECKED(JSObject, obj, 0);
3661 CONVERT_ARG_CHECKED(String, name, 1);
3662
3663 LookupResult result;
3664 obj->Lookup(*name, &result);
3665 if (result.IsProperty()) {
3666 return DebugLookupResultValue(&result);
3667 }
3668 return Heap::undefined_value();
3669}
3670
3671
3672// Return the names of the local named properties.
3673// args[0]: object
3674static Object* Runtime_DebugLocalPropertyNames(Arguments args) {
3675 HandleScope scope;
3676 ASSERT(args.length() == 1);
3677 if (!args[0]->IsJSObject()) {
3678 return Heap::undefined_value();
3679 }
3680 CONVERT_ARG_CHECKED(JSObject, obj, 0);
3681
3682 int n = obj->NumberOfLocalProperties(static_cast<PropertyAttributes>(NONE));
3683 Handle<FixedArray> names = Factory::NewFixedArray(n);
3684 obj->GetLocalPropertyNames(*names);
3685 return *Factory::NewJSArrayWithElements(names);
3686}
3687
3688
3689// Return the names of the local indexed properties.
3690// args[0]: object
3691static Object* Runtime_DebugLocalElementNames(Arguments args) {
3692 HandleScope scope;
3693 ASSERT(args.length() == 1);
3694 if (!args[0]->IsJSObject()) {
3695 return Heap::undefined_value();
3696 }
3697 CONVERT_ARG_CHECKED(JSObject, obj, 0);
3698
3699 int n = obj->NumberOfLocalElements(static_cast<PropertyAttributes>(NONE));
3700 Handle<FixedArray> names = Factory::NewFixedArray(n);
3701 obj->GetLocalElementKeys(*names, static_cast<PropertyAttributes>(NONE));
3702 return *Factory::NewJSArrayWithElements(names);
3703}
3704
3705
3706// Return the property type calculated from the property details.
3707// args[0]: smi with property details.
3708static Object* Runtime_DebugPropertyTypeFromDetails(Arguments args) {
3709 ASSERT(args.length() == 1);
3710 CONVERT_CHECKED(Smi, details, args[0]);
3711 PropertyType type = PropertyDetails(details).type();
3712 return Smi::FromInt(static_cast<int>(type));
3713}
3714
3715
3716// Return the property attribute calculated from the property details.
3717// args[0]: smi with property details.
3718static Object* Runtime_DebugPropertyAttributesFromDetails(Arguments args) {
3719 ASSERT(args.length() == 1);
3720 CONVERT_CHECKED(Smi, details, args[0]);
3721 PropertyAttributes attributes = PropertyDetails(details).attributes();
3722 return Smi::FromInt(static_cast<int>(attributes));
3723}
3724
3725
3726// Return the property insertion index calculated from the property details.
3727// args[0]: smi with property details.
3728static Object* Runtime_DebugPropertyIndexFromDetails(Arguments args) {
3729 ASSERT(args.length() == 1);
3730 CONVERT_CHECKED(Smi, details, args[0]);
3731 int index = PropertyDetails(details).index();
3732 return Smi::FromInt(index);
3733}
3734
3735
3736// Return information on whether an object has a named or indexed interceptor.
3737// args[0]: object
3738static Object* Runtime_DebugInterceptorInfo(Arguments args) {
3739 HandleScope scope;
3740 ASSERT(args.length() == 1);
3741 if (!args[0]->IsJSObject()) {
3742 return Smi::FromInt(0);
3743 }
3744 CONVERT_ARG_CHECKED(JSObject, obj, 0);
3745
3746 int result = 0;
3747 if (obj->HasNamedInterceptor()) result |= 2;
3748 if (obj->HasIndexedInterceptor()) result |= 1;
3749
3750 return Smi::FromInt(result);
3751}
3752
3753
3754// Return property names from named interceptor.
3755// args[0]: object
3756static Object* Runtime_DebugNamedInterceptorPropertyNames(Arguments args) {
3757 HandleScope scope;
3758 ASSERT(args.length() == 1);
3759 CONVERT_ARG_CHECKED(JSObject, obj, 0);
3760 RUNTIME_ASSERT(obj->HasNamedInterceptor());
3761
3762 v8::Handle<v8::Array> result = GetKeysForNamedInterceptor(obj, obj);
3763 if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
3764 return Heap::undefined_value();
3765}
3766
3767
3768// Return element names from indexed interceptor.
3769// args[0]: object
3770static Object* Runtime_DebugIndexedInterceptorElementNames(Arguments args) {
3771 HandleScope scope;
3772 ASSERT(args.length() == 1);
3773 CONVERT_ARG_CHECKED(JSObject, obj, 0);
3774 RUNTIME_ASSERT(obj->HasIndexedInterceptor());
3775
3776 v8::Handle<v8::Array> result = GetKeysForIndexedInterceptor(obj, obj);
3777 if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
3778 return Heap::undefined_value();
3779}
3780
3781
3782// Return property value from named interceptor.
3783// args[0]: object
3784// args[1]: property name
3785static Object* Runtime_DebugNamedInterceptorPropertyValue(Arguments args) {
3786 HandleScope scope;
3787 ASSERT(args.length() == 2);
3788 CONVERT_ARG_CHECKED(JSObject, obj, 0);
3789 RUNTIME_ASSERT(obj->HasNamedInterceptor());
3790 CONVERT_ARG_CHECKED(String, name, 1);
3791
3792 PropertyAttributes attributes;
3793 Object* result = obj->GetPropertyWithInterceptor(*obj, *name, &attributes);
3794 return result;
3795}
3796
3797
3798// Return element value from indexed interceptor.
3799// args[0]: object
3800// args[1]: index
3801static Object* Runtime_DebugIndexedInterceptorElementValue(Arguments args) {
3802 HandleScope scope;
3803 ASSERT(args.length() == 2);
3804 CONVERT_ARG_CHECKED(JSObject, obj, 0);
3805 RUNTIME_ASSERT(obj->HasIndexedInterceptor());
3806 CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
3807
3808 Object* result = obj->GetElementWithInterceptor(*obj, index);
3809 return result;
3810}
3811
3812
3813static Object* Runtime_CheckExecutionState(Arguments args) {
3814 ASSERT(args.length() >= 1);
3815 CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
3816 // Check that the break id is valid and that there is a valid frame
3817 // where execution is broken.
3818 if (break_id != Top::break_id() ||
3819 Top::break_frame_id() == StackFrame::NO_ID) {
3820 return Top::Throw(Heap::illegal_execution_state_symbol());
3821 }
3822
3823 return Heap::true_value();
3824}
3825
3826
3827static Object* Runtime_GetFrameCount(Arguments args) {
3828 HandleScope scope;
3829 ASSERT(args.length() == 1);
3830
3831 // Check arguments.
3832 Object* result = Runtime_CheckExecutionState(args);
3833 if (result->IsFailure()) return result;
3834
3835 // Count all frames which are relevant to debugging stack trace.
3836 int n = 0;
3837 StackFrame::Id id = Top::break_frame_id();
3838 for (JavaScriptFrameIterator it(id); !it.done(); it.Advance()) n++;
3839 return Smi::FromInt(n);
3840}
3841
3842
3843static const int kFrameDetailsFrameIdIndex = 0;
3844static const int kFrameDetailsReceiverIndex = 1;
3845static const int kFrameDetailsFunctionIndex = 2;
3846static const int kFrameDetailsArgumentCountIndex = 3;
3847static const int kFrameDetailsLocalCountIndex = 4;
3848static const int kFrameDetailsSourcePositionIndex = 5;
3849static const int kFrameDetailsConstructCallIndex = 6;
3850static const int kFrameDetailsDebuggerFrameIndex = 7;
3851static const int kFrameDetailsFirstDynamicIndex = 8;
3852
3853// Return an array with frame details
3854// args[0]: number: break id
3855// args[1]: number: frame index
3856//
3857// The array returned contains the following information:
3858// 0: Frame id
3859// 1: Receiver
3860// 2: Function
3861// 3: Argument count
3862// 4: Local count
3863// 5: Source position
3864// 6: Constructor call
3865// 7: Debugger frame
3866// Arguments name, value
3867// Locals name, value
3868static Object* Runtime_GetFrameDetails(Arguments args) {
3869 HandleScope scope;
3870 ASSERT(args.length() == 2);
3871
3872 // Check arguments.
3873 Object* result = Runtime_CheckExecutionState(args);
3874 if (result->IsFailure()) return result;
3875 CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
3876
3877 // Find the relevant frame with the requested index.
3878 StackFrame::Id id = Top::break_frame_id();
3879 int count = 0;
3880 JavaScriptFrameIterator it(id);
3881 for (; !it.done(); it.Advance()) {
3882 if (count == index) break;
3883 count++;
3884 }
3885 if (it.done()) return Heap::undefined_value();
3886
3887 // Traverse the saved contexts chain to find the active context for the
3888 // selected frame.
3889 SaveContext* save = Top::save_context();
3890 while (save != NULL && reinterpret_cast<Address>(save) < it.frame()->sp()) {
3891 save = save->prev();
3892 }
3893
3894 // Get the frame id.
3895 Handle<Object> frame_id(WrapFrameId(it.frame()->id()));
3896
3897 // Find source position.
3898 int position = it.frame()->FindCode()->SourcePosition(it.frame()->pc());
3899
3900 // Check for constructor frame.
3901 bool constructor = it.frame()->IsConstructor();
3902
3903 // Get code and read scope info from it for local variable information.
3904 Handle<Code> code(it.frame()->FindCode());
3905 ScopeInfo<> info(*code);
3906
3907 // Get the context.
3908 Handle<Context> context(Context::cast(it.frame()->context()));
3909
3910 // Get the locals names and values into a temporary array.
3911 //
3912 // TODO(1240907): Hide compiler-introduced stack variables
3913 // (e.g. .result)? For users of the debugger, they will probably be
3914 // confusing.
3915 Handle<FixedArray> locals = Factory::NewFixedArray(info.NumberOfLocals() * 2);
3916 for (int i = 0; i < info.NumberOfLocals(); i++) {
3917 // Name of the local.
3918 locals->set(i * 2, *info.LocalName(i));
3919
3920 // Fetch the value of the local - either from the stack or from a
3921 // heap-allocated context.
3922 if (i < info.number_of_stack_slots()) {
3923 locals->set(i * 2 + 1, it.frame()->GetExpression(i));
3924 } else {
3925 Handle<String> name = info.LocalName(i);
3926 // Traverse the context chain to the function context as all local
3927 // variables stored in the context will be on the function context.
3928 while (context->previous() != NULL) {
3929 context = Handle<Context>(context->previous());
3930 }
3931 ASSERT(context->is_function_context());
3932 locals->set(i * 2 + 1,
3933 context->get(ScopeInfo<>::ContextSlotIndex(*code, *name,
3934 NULL)));
3935 }
3936 }
3937
3938 // Now advance to the arguments adapter frame (if any). If contains all
3939 // the provided parameters and
3940
3941 // Now advance to the arguments adapter frame (if any). It contains all
3942 // the provided parameters whereas the function frame always have the number
3943 // of arguments matching the functions parameters. The rest of the
3944 // information (except for what is collected above) is the same.
3945 it.AdvanceToArgumentsFrame();
3946
3947 // Find the number of arguments to fill. At least fill the number of
3948 // parameters for the function and fill more if more parameters are provided.
3949 int argument_count = info.number_of_parameters();
3950 if (argument_count < it.frame()->GetProvidedParametersCount()) {
3951 argument_count = it.frame()->GetProvidedParametersCount();
3952 }
3953
3954 // Calculate the size of the result.
3955 int details_size = kFrameDetailsFirstDynamicIndex +
3956 2 * (argument_count + info.NumberOfLocals());
3957 Handle<FixedArray> details = Factory::NewFixedArray(details_size);
3958
3959 // Add the frame id.
3960 details->set(kFrameDetailsFrameIdIndex, *frame_id);
3961
3962 // Add the function (same as in function frame).
3963 details->set(kFrameDetailsFunctionIndex, it.frame()->function());
3964
3965 // Add the arguments count.
3966 details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
3967
3968 // Add the locals count
3969 details->set(kFrameDetailsLocalCountIndex,
3970 Smi::FromInt(info.NumberOfLocals()));
3971
3972 // Add the source position.
3973 if (position != kNoPosition) {
3974 details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
3975 } else {
3976 details->set(kFrameDetailsSourcePositionIndex, Heap::undefined_value());
3977 }
3978
3979 // Add the constructor information.
3980 details->set(kFrameDetailsConstructCallIndex, Heap::ToBoolean(constructor));
3981
3982 // Add information on whether this frame is invoked in the debugger context.
3983 details->set(kFrameDetailsDebuggerFrameIndex,
3984 Heap::ToBoolean(*save->context() == *Debug::debug_context()));
3985
3986 // Fill the dynamic part.
3987 int details_index = kFrameDetailsFirstDynamicIndex;
3988
3989 // Add arguments name and value.
3990 for (int i = 0; i < argument_count; i++) {
3991 // Name of the argument.
3992 if (i < info.number_of_parameters()) {
3993 details->set(details_index++, *info.parameter_name(i));
3994 } else {
3995 details->set(details_index++, Heap::undefined_value());
3996 }
3997
3998 // Parameter value.
3999 if (i < it.frame()->GetProvidedParametersCount()) {
4000 details->set(details_index++, it.frame()->GetParameter(i));
4001 } else {
4002 details->set(details_index++, Heap::undefined_value());
4003 }
4004 }
4005
4006 // Add locals name and value from the temporary copy from the function frame.
4007 for (int i = 0; i < info.NumberOfLocals() * 2; i++) {
4008 details->set(details_index++, locals->get(i));
4009 }
4010
4011 // Add the receiver (same as in function frame).
4012 // THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
4013 // THE FRAME ITERATOR TO WRAP THE RECEIVER.
4014 Handle<Object> receiver(it.frame()->receiver());
4015 if (!receiver->IsJSObject()) {
4016 // If the receiver is NOT a JSObject we have hit an optimization
4017 // where a value object is not converted into a wrapped JS objects.
4018 // To hide this optimization from the debugger, we wrap the receiver
4019 // by creating correct wrapper object based on the calling frame's
4020 // global context.
4021 it.Advance();
4022 Handle<Context> calling_frames_global_context(
4023 Context::cast(Context::cast(it.frame()->context())->global_context()));
4024 receiver = Factory::ToObject(receiver, calling_frames_global_context);
4025 }
4026 details->set(kFrameDetailsReceiverIndex, *receiver);
4027
4028 ASSERT_EQ(details_size, details_index);
4029 return *Factory::NewJSArrayWithElements(details);
4030}
4031
4032
4033static Object* Runtime_GetCFrames(Arguments args) {
4034 HandleScope scope;
4035 ASSERT(args.length() == 1);
4036 Object* result = Runtime_CheckExecutionState(args);
4037 if (result->IsFailure()) return result;
4038
4039 static const int kMaxCFramesSize = 200;
4040 OS::StackFrame frames[kMaxCFramesSize];
4041 int frames_count = OS::StackWalk(frames, kMaxCFramesSize);
4042 if (frames_count == OS::kStackWalkError) {
4043 return Heap::undefined_value();
4044 }
4045
4046 Handle<String> address_str = Factory::LookupAsciiSymbol("address");
4047 Handle<String> text_str = Factory::LookupAsciiSymbol("text");
4048 Handle<FixedArray> frames_array = Factory::NewFixedArray(frames_count);
4049 for (int i = 0; i < frames_count; i++) {
4050 Handle<JSObject> frame_value = Factory::NewJSObject(Top::object_function());
4051 frame_value->SetProperty(
4052 *address_str,
4053 *Factory::NewNumberFromInt(reinterpret_cast<int>(frames[i].address)),
4054 NONE);
4055
4056 // Get the stack walk text for this frame.
4057 Handle<String> frame_text;
4058 if (strlen(frames[i].text) > 0) {
4059 Vector<const char> str(frames[i].text, strlen(frames[i].text));
4060 frame_text = Factory::NewStringFromAscii(str);
4061 }
4062
4063 if (!frame_text.is_null()) {
4064 frame_value->SetProperty(*text_str, *frame_text, NONE);
4065 }
4066
4067 frames_array->set(i, *frame_value);
4068 }
4069 return *Factory::NewJSArrayWithElements(frames_array);
4070}
4071
4072
4073static Object* Runtime_GetBreakLocations(Arguments args) {
4074 HandleScope scope;
4075 ASSERT(args.length() == 1);
4076
4077 CONVERT_ARG_CHECKED(JSFunction, raw_fun, 0);
4078 Handle<SharedFunctionInfo> shared(raw_fun->shared());
4079 // Find the number of break points
4080 Handle<Object> break_locations = Debug::GetSourceBreakLocations(shared);
4081 if (break_locations->IsUndefined()) return Heap::undefined_value();
4082 // Return array as JS array
4083 return *Factory::NewJSArrayWithElements(
4084 Handle<FixedArray>::cast(break_locations));
4085}
4086
4087
4088// Set a break point in a function
4089// args[0]: function
4090// args[1]: number: break source position (within the function source)
4091// args[2]: number: break point object
4092static Object* Runtime_SetFunctionBreakPoint(Arguments args) {
4093 HandleScope scope;
4094 ASSERT(args.length() == 3);
4095 CONVERT_ARG_CHECKED(JSFunction, raw_fun, 0);
4096 Handle<SharedFunctionInfo> shared(raw_fun->shared());
4097 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
4098 RUNTIME_ASSERT(source_position >= 0);
4099 Handle<Object> break_point_object_arg = args.at<Object>(2);
4100
4101 // Set break point.
4102 Debug::SetBreakPoint(shared, source_position, break_point_object_arg);
4103
4104 return Heap::undefined_value();
4105}
4106
4107
4108static Object* FindSharedFunctionInfoInScript(Handle<Script> script,
4109 int position) {
4110 // Iterate the heap looking for SharedFunctionInfo generated from the
4111 // script. The inner most SharedFunctionInfo containing the source position
4112 // for the requested break point is found.
4113 // NOTE: This might reqire several heap iterations. If the SharedFunctionInfo
4114 // which is found is not compiled it is compiled and the heap is iterated
4115 // again as the compilation might create inner functions from the newly
4116 // compiled function and the actual requested break point might be in one of
4117 // these functions.
4118 bool done = false;
4119 // The current candidate for the source position:
4120 int target_start_position = kNoPosition;
4121 Handle<SharedFunctionInfo> target;
4122 // The current candidate for the last function in script:
4123 Handle<SharedFunctionInfo> last;
4124 while (!done) {
4125 HeapIterator iterator;
4126 while (iterator.has_next()) {
4127 HeapObject* obj = iterator.next();
4128 ASSERT(obj != NULL);
4129 if (obj->IsSharedFunctionInfo()) {
4130 Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(obj));
4131 if (shared->script() == *script) {
4132 // If the SharedFunctionInfo found has the requested script data and
4133 // contains the source position it is a candidate.
4134 int start_position = shared->function_token_position();
4135 if (start_position == kNoPosition) {
4136 start_position = shared->start_position();
4137 }
4138 if (start_position <= position &&
4139 position <= shared->end_position()) {
4140 // If there is no candidate or this function is within the currrent
4141 // candidate this is the new candidate.
4142 if (target.is_null()) {
4143 target_start_position = start_position;
4144 target = shared;
4145 } else {
4146 if (target_start_position < start_position &&
4147 shared->end_position() < target->end_position()) {
4148 target_start_position = start_position;
4149 target = shared;
4150 }
4151 }
4152 }
4153
4154 // Keep track of the last function in the script.
4155 if (last.is_null() ||
4156 shared->end_position() > last->start_position()) {
4157 last = shared;
4158 }
4159 }
4160 }
4161 }
4162
4163 // Make sure some candidate is selected.
4164 if (target.is_null()) {
4165 if (!last.is_null()) {
4166 // Position after the last function - use last.
4167 target = last;
4168 } else {
4169 // Unable to find function - possibly script without any function.
4170 return Heap::undefined_value();
4171 }
4172 }
4173
4174 // If the candidate found is compiled we are done. NOTE: when lazy
4175 // compilation of inner functions is introduced some additional checking
4176 // needs to be done here to compile inner functions.
4177 done = target->is_compiled();
4178 if (!done) {
4179 // If the candidate is not compiled compile it to reveal any inner
4180 // functions which might contain the requested source position.
4181 CompileLazyShared(target, KEEP_EXCEPTION);
4182 }
4183 }
4184
4185 return *target;
4186}
4187
4188
4189// Change the state of a break point in a script. NOTE: Regarding performance
4190// see the NOTE for GetScriptFromScriptData.
4191// args[0]: script to set break point in
4192// args[1]: number: break source position (within the script source)
4193// args[2]: number: break point object
4194static Object* Runtime_SetScriptBreakPoint(Arguments args) {
4195 HandleScope scope;
4196 ASSERT(args.length() == 3);
4197 CONVERT_ARG_CHECKED(JSValue, wrapper, 0);
4198 CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
4199 RUNTIME_ASSERT(source_position >= 0);
4200 Handle<Object> break_point_object_arg = args.at<Object>(2);
4201
4202 // Get the script from the script wrapper.
4203 RUNTIME_ASSERT(wrapper->value()->IsScript());
4204 Handle<Script> script(Script::cast(wrapper->value()));
4205
4206 Object* result = FindSharedFunctionInfoInScript(script, source_position);
4207 if (!result->IsUndefined()) {
4208 Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result));
4209 // Find position within function. The script position might be before the
4210 // source position of the first function.
4211 int position;
4212 if (shared->start_position() > source_position) {
4213 position = 0;
4214 } else {
4215 position = source_position - shared->start_position();
4216 }
4217 Debug::SetBreakPoint(shared, position, break_point_object_arg);
4218 }
4219 return Heap::undefined_value();
4220}
4221
4222
4223// Clear a break point
4224// args[0]: number: break point object
4225static Object* Runtime_ClearBreakPoint(Arguments args) {
4226 HandleScope scope;
4227 ASSERT(args.length() == 1);
4228 Handle<Object> break_point_object_arg = args.at<Object>(0);
4229
4230 // Clear break point.
4231 Debug::ClearBreakPoint(break_point_object_arg);
4232
4233 return Heap::undefined_value();
4234}
4235
4236
4237// Change the state of break on exceptions
4238// args[0]: boolean indicating uncaught exceptions
4239// args[1]: boolean indicating on/off
4240static Object* Runtime_ChangeBreakOnException(Arguments args) {
4241 HandleScope scope;
4242 ASSERT(args.length() == 2);
4243 ASSERT(args[0]->IsNumber());
4244 ASSERT(args[1]->IsBoolean());
4245
4246 // Update break point state
4247 ExceptionBreakType type =
4248 static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
4249 bool enable = args[1]->ToBoolean()->IsTrue();
4250 Debug::ChangeBreakOnException(type, enable);
4251 return Heap::undefined_value();
4252}
4253
4254
4255// Prepare for stepping
4256// args[0]: break id for checking execution state
4257// args[1]: step action from the enumeration StepAction
4258// args[2]: number of times to perform the step
4259static Object* Runtime_PrepareStep(Arguments args) {
4260 HandleScope scope;
4261 ASSERT(args.length() == 3);
4262 // Check arguments.
4263 Object* check_result = Runtime_CheckExecutionState(args);
4264 if (check_result->IsFailure()) return check_result;
4265 if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
4266 return Top::Throw(Heap::illegal_argument_symbol());
4267 }
4268
4269 // Get the step action and check validity.
4270 StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
4271 if (step_action != StepIn &&
4272 step_action != StepNext &&
4273 step_action != StepOut &&
4274 step_action != StepInMin &&
4275 step_action != StepMin) {
4276 return Top::Throw(Heap::illegal_argument_symbol());
4277 }
4278
4279 // Get the number of steps.
4280 int step_count = NumberToInt32(args[2]);
4281 if (step_count < 1) {
4282 return Top::Throw(Heap::illegal_argument_symbol());
4283 }
4284
4285 // Prepare step.
4286 Debug::PrepareStep(static_cast<StepAction>(step_action), step_count);
4287 return Heap::undefined_value();
4288}
4289
4290
4291// Clear all stepping set by PrepareStep.
4292static Object* Runtime_ClearStepping(Arguments args) {
4293 HandleScope scope;
4294 ASSERT(args.length() == 1);
4295 Debug::ClearStepping();
4296 return Heap::undefined_value();
4297}
4298
4299
4300// Creates a copy of the with context chain. The copy of the context chain is
4301// is linked to the function context supplied.
4302static Handle<Context> CopyWithContextChain(Handle<Context> context_chain,
4303 Handle<Context> function_context) {
4304 // At the bottom of the chain. Return the function context to link to.
4305 if (context_chain->is_function_context()) {
4306 return function_context;
4307 }
4308
4309 // Recursively copy the with contexts.
4310 Handle<Context> previous(context_chain->previous());
4311 Handle<JSObject> extension(JSObject::cast(context_chain->extension()));
4312 return Factory::NewWithContext(
4313 CopyWithContextChain(function_context, previous), extension);
4314}
4315
4316
4317// Helper function to find or create the arguments object for
4318// Runtime_DebugEvaluate.
4319static Handle<Object> GetArgumentsObject(JavaScriptFrame* frame,
4320 Handle<JSFunction> function,
4321 Handle<Code> code,
4322 const ScopeInfo<>* sinfo,
4323 Handle<Context> function_context) {
4324 // Try to find the value of 'arguments' to pass as parameter. If it is not
4325 // found (that is the debugged function does not reference 'arguments' and
4326 // does not support eval) then create an 'arguments' object.
4327 int index;
4328 if (sinfo->number_of_stack_slots() > 0) {
4329 index = ScopeInfo<>::StackSlotIndex(*code, Heap::arguments_symbol());
4330 if (index != -1) {
4331 return Handle<Object>(frame->GetExpression(index));
4332 }
4333 }
4334
4335 if (sinfo->number_of_context_slots() > Context::MIN_CONTEXT_SLOTS) {
4336 index = ScopeInfo<>::ContextSlotIndex(*code, Heap::arguments_symbol(),
4337 NULL);
4338 if (index != -1) {
4339 return Handle<Object>(function_context->get(index));
4340 }
4341 }
4342
4343 const int length = frame->GetProvidedParametersCount();
4344 Handle<Object> arguments = Factory::NewArgumentsObject(function, length);
4345 FixedArray* array = FixedArray::cast(JSObject::cast(*arguments)->elements());
4346 ASSERT(array->length() == length);
4347 for (int i = 0; i < length; i++) {
4348 array->set(i, frame->GetParameter(i));
4349 }
4350 return arguments;
4351}
4352
4353
4354// Evaluate a piece of JavaScript in the context of a stack frame for
4355// debugging. This is acomplished by creating a new context which in its
4356// extension part has all the parameters and locals of the function on the
4357// stack frame. A function which calls eval with the code to evaluate is then
4358// compiled in this context and called in this context. As this context
4359// replaces the context of the function on the stack frame a new (empty)
4360// function is created as well to be used as the closure for the context.
4361// This function and the context acts as replacements for the function on the
4362// stack frame presenting the same view of the values of parameters and
4363// local variables as if the piece of JavaScript was evaluated at the point
4364// where the function on the stack frame is currently stopped.
4365static Object* Runtime_DebugEvaluate(Arguments args) {
4366 HandleScope scope;
4367
4368 // Check the execution state and decode arguments frame and source to be
4369 // evaluated.
kasper.lundbd3ec4e2008-07-09 11:06:54 +00004370 ASSERT(args.length() == 4);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004371 Object* check_result = Runtime_CheckExecutionState(args);
4372 if (check_result->IsFailure()) return check_result;
4373 CONVERT_CHECKED(Smi, wrapped_id, args[1]);
4374 CONVERT_ARG_CHECKED(String, source, 2);
kasper.lundbd3ec4e2008-07-09 11:06:54 +00004375 CONVERT_BOOLEAN_CHECKED(disable_break, args[3]);
4376
4377 // Handle the processing of break.
4378 DisableBreak disable_break_save(disable_break);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004379
4380 // Get the frame where the debugging is performed.
4381 StackFrame::Id id = UnwrapFrameId(wrapped_id);
4382 JavaScriptFrameIterator it(id);
4383 JavaScriptFrame* frame = it.frame();
4384 Handle<JSFunction> function(JSFunction::cast(frame->function()));
4385 Handle<Code> code(function->code());
4386 ScopeInfo<> sinfo(*code);
4387
4388 // Traverse the saved contexts chain to find the active context for the
4389 // selected frame.
4390 SaveContext* save = Top::save_context();
4391 while (save != NULL && reinterpret_cast<Address>(save) < frame->sp()) {
4392 save = save->prev();
4393 }
4394 ASSERT(save != NULL);
4395 SaveContext savex;
4396 Top::set_context(*(save->context()));
4397 Top::set_security_context(*(save->security_context()));
4398
4399 // Create the (empty) function replacing the function on the stack frame for
4400 // the purpose of evaluating in the context created below. It is important
4401 // that this function does not describe any parameters and local variables
4402 // in the context. If it does then this will cause problems with the lookup
4403 // in Context::Lookup, where context slots for parameters and local variables
4404 // are looked at before the extension object.
4405 Handle<JSFunction> go_between =
4406 Factory::NewFunction(Factory::empty_string(), Factory::undefined_value());
4407 go_between->set_context(function->context());
4408#ifdef DEBUG
4409 ScopeInfo<> go_between_sinfo(go_between->shared()->code());
4410 ASSERT(go_between_sinfo.number_of_parameters() == 0);
4411 ASSERT(go_between_sinfo.number_of_context_slots() == 0);
4412#endif
4413
4414 // Allocate and initialize a context extension object with all the
4415 // arguments, stack locals heap locals and extension properties of the
4416 // debugged function.
4417 Handle<JSObject> context_ext = Factory::NewJSObject(Top::object_function());
4418 // First fill all parameters to the context extension.
4419 for (int i = 0; i < sinfo.number_of_parameters(); ++i) {
4420 SetProperty(context_ext,
4421 sinfo.parameter_name(i),
4422 Handle<Object>(frame->GetParameter(i)), NONE);
4423 }
4424 // Second fill all stack locals to the context extension.
4425 for (int i = 0; i < sinfo.number_of_stack_slots(); i++) {
4426 SetProperty(context_ext,
4427 sinfo.stack_slot_name(i),
4428 Handle<Object>(frame->GetExpression(i)), NONE);
4429 }
4430 // Third fill all context locals to the context extension.
4431 Handle<Context> frame_context(Context::cast(frame->context()));
4432 Handle<Context> function_context(frame_context->fcontext());
4433 for (int i = Context::MIN_CONTEXT_SLOTS;
4434 i < sinfo.number_of_context_slots();
4435 ++i) {
4436 int context_index =
4437 ScopeInfo<>::ContextSlotIndex(*code, *sinfo.context_slot_name(i), NULL);
4438 SetProperty(context_ext,
4439 sinfo.context_slot_name(i),
4440 Handle<Object>(function_context->get(context_index)), NONE);
4441 }
4442 // Finally copy any properties from the function context extension. This will
4443 // be variables introduced by eval.
4444 if (function_context->extension() != NULL &&
4445 !function_context->IsGlobalContext()) {
4446 Handle<JSObject> ext(JSObject::cast(function_context->extension()));
4447 Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext);
4448 for (int i = 0; i < keys->length(); i++) {
4449 // Names of variables introduced by eval are strings.
4450 ASSERT(keys->get(i)->IsString());
4451 Handle<String> key(String::cast(keys->get(i)));
4452 SetProperty(context_ext, key, GetProperty(ext, key), NONE);
4453 }
4454 }
4455
4456 // Allocate a new context for the debug evaluation and set the extension
4457 // object build.
4458 Handle<Context> context =
4459 Factory::NewFunctionContext(Context::MIN_CONTEXT_SLOTS, go_between);
4460 context->set_extension(*context_ext);
4461 // Copy any with contexts present and chain them in front of this context.
4462 context = CopyWithContextChain(frame_context, context);
4463
4464 // Wrap the evaluation statement in a new function compiled in the newly
4465 // created context. The function has one parameter which has to be called
4466 // 'arguments'. This it to have access to what would have been 'arguments' in
4467 // the function beeing debugged.
4468 // function(arguments,__source__) {return eval(__source__);}
4469 static const char* source_str =
4470 "function(arguments,__source__){return eval(__source__);}";
4471 static const int source_str_length = strlen(source_str);
4472 Handle<String> function_source =
4473 Factory::NewStringFromAscii(Vector<const char>(source_str,
4474 source_str_length));
4475 Handle<JSFunction> boilerplate =
4476 Compiler::CompileEval(context->IsGlobalContext(), function_source);
4477 if (boilerplate.is_null()) return Failure::Exception();
4478 Handle<JSFunction> compiled_function =
4479 Factory::NewFunctionFromBoilerplate(boilerplate, context);
4480
4481 // Invoke the result of the compilation to get the evaluation function.
4482 bool has_pending_exception;
4483 Handle<Object> receiver(frame->receiver());
4484 Handle<Object> evaluation_function =
4485 Execution::Call(compiled_function, receiver, 0, NULL,
4486 &has_pending_exception);
4487
4488 Handle<Object> arguments = GetArgumentsObject(frame, function, code, &sinfo,
4489 function_context);
4490
4491 // Invoke the evaluation function and return the result.
4492 const int argc = 2;
4493 Object** argv[argc] = { arguments.location(),
4494 Handle<Object>::cast(source).location() };
4495 Handle<Object> result =
4496 Execution::Call(Handle<JSFunction>::cast(evaluation_function), receiver,
4497 argc, argv, &has_pending_exception);
4498 return *result;
4499}
4500
4501
4502static Object* Runtime_DebugEvaluateGlobal(Arguments args) {
4503 HandleScope scope;
4504
4505 // Check the execution state and decode arguments frame and source to be
4506 // evaluated.
kasper.lundbd3ec4e2008-07-09 11:06:54 +00004507 ASSERT(args.length() == 3);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004508 Object* check_result = Runtime_CheckExecutionState(args);
4509 if (check_result->IsFailure()) return check_result;
4510 CONVERT_ARG_CHECKED(String, source, 1);
kasper.lundbd3ec4e2008-07-09 11:06:54 +00004511 CONVERT_BOOLEAN_CHECKED(disable_break, args[2]);
4512
4513 // Handle the processing of break.
4514 DisableBreak disable_break_save(disable_break);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004515
4516 // Enter the top context from before the debugger was invoked.
4517 SaveContext save;
4518 SaveContext* top = &save;
4519 while (top != NULL && *top->context() == *Debug::debug_context()) {
4520 top = top->prev();
4521 }
4522 if (top != NULL) {
4523 Top::set_context(*top->context());
4524 Top::set_security_context(*top->security_context());
4525 }
4526
4527 // Get the global context now set to the top context from before the
4528 // debugger was invoked.
4529 Handle<Context> context = Top::global_context();
4530
4531 // Compile the source to be evaluated.
4532 Handle<JSFunction> boilerplate(Compiler::CompileEval(true, source));
4533 if (boilerplate.is_null()) return Failure::Exception();
4534 Handle<JSFunction> compiled_function =
4535 Handle<JSFunction>(Factory::NewFunctionFromBoilerplate(boilerplate,
4536 context));
4537
4538 // Invoke the result of the compilation to get the evaluation function.
4539 bool has_pending_exception;
4540 Handle<Object> receiver = Top::global();
4541 Handle<Object> result =
4542 Execution::Call(compiled_function, receiver, 0, NULL,
4543 &has_pending_exception);
4544 return *result;
4545}
4546
4547
4548// Helper function used by Runtime_DebugGetLoadedScripts below.
4549static int DebugGetLoadedScripts(FixedArray* instances, int instances_size) {
4550 NoHandleAllocation ha;
4551 AssertNoAllocation no_alloc;
4552
4553 // Get hold of the current empty script.
4554 Context* context = Top::context()->global_context();
4555 Script* empty = context->empty_script();
4556
4557 // Scan heap for Script objects.
4558 int count = 0;
4559 HeapIterator iterator;
4560 while (iterator.has_next()) {
4561 HeapObject* obj = iterator.next();
4562 ASSERT(obj != NULL);
4563 if (obj->IsScript() && obj != empty) {
4564 if (instances != NULL && count < instances_size) {
4565 instances->set(count, obj);
4566 }
4567 count++;
4568 }
4569 }
4570
4571 return count;
4572}
4573
4574
4575static Object* Runtime_DebugGetLoadedScripts(Arguments args) {
4576 HandleScope scope;
4577 ASSERT(args.length() == 1);
4578
4579 // Perform two GCs to get rid of all unreferenced scripts. The first GC gets
4580 // rid of all the cached script wrappes and the second gets rid of the
4581 // scripts which is no longer referenced.
4582 Heap::CollectGarbage(0, OLD_SPACE);
4583 Heap::CollectGarbage(0, OLD_SPACE);
4584
4585 // Get the number of scripts.
4586 int count;
4587 count = DebugGetLoadedScripts(NULL, 0);
4588
4589 // Allocate an array to hold the result.
4590 Handle<FixedArray> instances = Factory::NewFixedArray(count);
4591
4592 // Fill the script objects.
4593 count = DebugGetLoadedScripts(*instances, count);
4594
4595 // Convert the script objects to proper JS objects.
4596 for (int i = 0; i < count; i++) {
4597 Handle<Script> script(Script::cast(instances->get(i)));
4598 instances->set(i, *GetScriptWrapper(script));
4599 }
4600
4601 // Return result as a JS array.
4602 Handle<JSObject> result = Factory::NewJSObject(Top::array_function());
4603 Handle<JSArray>::cast(result)->SetContent(*instances);
4604 return *result;
4605}
4606
4607
4608// Helper function used by Runtime_DebugReferencedBy below.
4609static int DebugReferencedBy(JSObject* target,
4610 Object* instance_filter, int max_references,
4611 FixedArray* instances, int instances_size,
4612 JSFunction* context_extension_function,
4613 JSFunction* arguments_function) {
4614 NoHandleAllocation ha;
4615 AssertNoAllocation no_alloc;
4616
4617 // Iterate the heap.
4618 int count = 0;
4619 JSObject* last = NULL;
4620 HeapIterator iterator;
4621 while (iterator.has_next() &&
4622 (max_references == 0 || count < max_references)) {
4623 // Only look at all JSObjects.
4624 HeapObject* heap_obj = iterator.next();
4625 if (heap_obj->IsJSObject()) {
4626 // Skip context extension objects and argument arrays as these are
4627 // checked in the context of functions using them.
4628 JSObject* obj = JSObject::cast(heap_obj);
4629 if (obj->map()->constructor() == context_extension_function ||
4630 obj->map()->constructor() == arguments_function) {
4631 continue;
4632 }
4633
4634 // Check if the JS object has a reference to the object looked for.
4635 if (obj->ReferencesObject(target)) {
4636 // Check instance filter if supplied. This is normally used to avoid
4637 // references from mirror objects (see Runtime_IsInPrototypeChain).
4638 if (!instance_filter->IsUndefined()) {
4639 Object* V = obj;
4640 while (true) {
4641 Object* prototype = V->GetPrototype();
4642 if (prototype->IsNull()) {
4643 break;
4644 }
4645 if (instance_filter == prototype) {
4646 obj = NULL; // Don't add this object.
4647 break;
4648 }
4649 V = prototype;
4650 }
4651 }
4652
4653 if (obj != NULL) {
4654 // Valid reference found add to instance array if supplied an update
4655 // count.
4656 if (instances != NULL && count < instances_size) {
4657 instances->set(count, obj);
4658 }
4659 last = obj;
4660 count++;
4661 }
4662 }
4663 }
4664 }
4665
4666 // Check for circular reference only. This can happen when the object is only
4667 // referenced from mirrors and has a circular reference in which case the
4668 // object is not really alive and would have been garbage collected if not
4669 // referenced from the mirror.
4670 if (count == 1 && last == target) {
4671 count = 0;
4672 }
4673
4674 // Return the number of referencing objects found.
4675 return count;
4676}
4677
4678
4679// Scan the heap for objects with direct references to an object
4680// args[0]: the object to find references to
4681// args[1]: constructor function for instances to exclude (Mirror)
4682// args[2]: the the maximum number of objects to return
4683static Object* Runtime_DebugReferencedBy(Arguments args) {
4684 ASSERT(args.length() == 3);
4685
4686 // First perform a full GC in order to avoid references from dead objects.
4687 Heap::CollectGarbage(0, OLD_SPACE);
4688
4689 // Check parameters.
4690 CONVERT_CHECKED(JSObject, target, args[0]);
4691 Object* instance_filter = args[1];
4692 RUNTIME_ASSERT(instance_filter->IsUndefined() ||
4693 instance_filter->IsJSObject());
4694 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
4695 RUNTIME_ASSERT(max_references >= 0);
4696
4697 // Get the constructor function for context extension and arguments array.
4698 JSFunction* context_extension_function =
4699 Top::context()->global_context()->context_extension_function();
4700 JSObject* arguments_boilerplate =
4701 Top::context()->global_context()->arguments_boilerplate();
4702 JSFunction* arguments_function =
4703 JSFunction::cast(arguments_boilerplate->map()->constructor());
4704
4705 // Get the number of referencing objects.
4706 int count;
4707 count = DebugReferencedBy(target, instance_filter, max_references,
4708 NULL, 0,
4709 context_extension_function, arguments_function);
4710
4711 // Allocate an array to hold the result.
4712 Object* object = Heap::AllocateFixedArray(count);
4713 if (object->IsFailure()) return object;
4714 FixedArray* instances = FixedArray::cast(object);
4715
4716 // Fill the referencing objects.
4717 count = DebugReferencedBy(target, instance_filter, max_references,
4718 instances, count,
4719 context_extension_function, arguments_function);
4720
4721 // Return result as JS array.
4722 Object* result =
4723 Heap::AllocateJSObject(
4724 Top::context()->global_context()->array_function());
4725 if (!result->IsFailure()) JSArray::cast(result)->SetContent(instances);
4726 return result;
4727}
4728
4729
4730// Helper function used by Runtime_DebugConstructedBy below.
4731static int DebugConstructedBy(JSFunction* constructor, int max_references,
4732 FixedArray* instances, int instances_size) {
4733 AssertNoAllocation no_alloc;
4734
4735 // Iterate the heap.
4736 int count = 0;
4737 HeapIterator iterator;
4738 while (iterator.has_next() &&
4739 (max_references == 0 || count < max_references)) {
4740 // Only look at all JSObjects.
4741 HeapObject* heap_obj = iterator.next();
4742 if (heap_obj->IsJSObject()) {
4743 JSObject* obj = JSObject::cast(heap_obj);
4744 if (obj->map()->constructor() == constructor) {
4745 // Valid reference found add to instance array if supplied an update
4746 // count.
4747 if (instances != NULL && count < instances_size) {
4748 instances->set(count, obj);
4749 }
4750 count++;
4751 }
4752 }
4753 }
4754
4755 // Return the number of referencing objects found.
4756 return count;
4757}
4758
4759
4760// Scan the heap for objects constructed by a specific function.
4761// args[0]: the constructor to find instances of
4762// args[1]: the the maximum number of objects to return
4763static Object* Runtime_DebugConstructedBy(Arguments args) {
4764 ASSERT(args.length() == 2);
4765
4766 // First perform a full GC in order to avoid dead objects.
4767 Heap::CollectGarbage(0, OLD_SPACE);
4768
4769 // Check parameters.
4770 CONVERT_CHECKED(JSFunction, constructor, args[0]);
4771 CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
4772 RUNTIME_ASSERT(max_references >= 0);
4773
4774 // Get the number of referencing objects.
4775 int count;
4776 count = DebugConstructedBy(constructor, max_references, NULL, 0);
4777
4778 // Allocate an array to hold the result.
4779 Object* object = Heap::AllocateFixedArray(count);
4780 if (object->IsFailure()) return object;
4781 FixedArray* instances = FixedArray::cast(object);
4782
4783 // Fill the referencing objects.
4784 count = DebugConstructedBy(constructor, max_references, instances, count);
4785
4786 // Return result as JS array.
4787 Object* result =
4788 Heap::AllocateJSObject(
4789 Top::context()->global_context()->array_function());
4790 if (!result->IsFailure()) JSArray::cast(result)->SetContent(instances);
4791 return result;
4792}
4793
4794
4795static Object* Runtime_GetPrototype(Arguments args) {
4796 ASSERT(args.length() == 1);
4797
4798 CONVERT_CHECKED(JSObject, obj, args[0]);
4799
4800 return obj->GetPrototype();
4801}
4802
4803
4804static Object* Runtime_SystemBreak(Arguments args) {
4805 CPU::DebugBreak();
4806 return Heap::undefined_value();
4807}
4808
4809
4810// Finds the script object from the script data. NOTE: This operation uses
4811// heap traversal to find the function generated for the source position
4812// for the requested break point. For lazily compiled functions several heap
4813// traversals might be required rendering this operation as a rather slow
4814// operation. However for setting break points which is normally done through
4815// some kind of user interaction the performance is not crucial.
4816static Handle<Object> Runtime_GetScriptFromScriptName(
4817 Handle<String> script_name) {
4818 // Scan the heap for Script objects to find the script with the requested
4819 // script data.
4820 Handle<Script> script;
4821 HeapIterator iterator;
4822 while (script.is_null() && iterator.has_next()) {
4823 HeapObject* obj = iterator.next();
4824 // If a script is found check if it has the script data requested.
4825 if (obj->IsScript()) {
4826 if (Script::cast(obj)->name()->IsString()) {
4827 if (String::cast(Script::cast(obj)->name())->Equals(*script_name)) {
4828 script = Handle<Script>(Script::cast(obj));
4829 }
4830 }
4831 }
4832 }
4833
4834 // If no script with the requested script data is found return undefined.
4835 if (script.is_null()) return Factory::undefined_value();
4836
4837 // Return the script found.
4838 return GetScriptWrapper(script);
4839}
4840
4841
4842// Get the script object from script data. NOTE: Regarding performance
4843// see the NOTE for GetScriptFromScriptData.
4844// args[0]: script data for the script to find the source for
4845static Object* Runtime_GetScript(Arguments args) {
4846 HandleScope scope;
4847
4848 ASSERT(args.length() == 1);
4849
4850 CONVERT_CHECKED(String, script_name, args[0]);
4851
4852 // Find the requested script.
4853 Handle<Object> result =
4854 Runtime_GetScriptFromScriptName(Handle<String>(script_name));
4855 return *result;
4856}
4857
4858
4859static Object* Runtime_FunctionGetAssemblerCode(Arguments args) {
4860#ifdef DEBUG
4861 HandleScope scope;
4862 ASSERT(args.length() == 1);
4863 // Get the function and make sure it is compiled.
4864 CONVERT_ARG_CHECKED(JSFunction, func, 0);
4865 if (!func->is_compiled() && !CompileLazy(func, KEEP_EXCEPTION)) {
4866 return Failure::Exception();
4867 }
4868 func->code()->PrintLn();
4869#endif // DEBUG
4870 return Heap::undefined_value();
4871}
4872
4873
4874static Object* Runtime_Abort(Arguments args) {
4875 ASSERT(args.length() == 2);
4876 OS::PrintError("abort: %s\n", reinterpret_cast<char*>(args[0]) +
4877 Smi::cast(args[1])->value());
4878 Top::PrintStack();
4879 OS::Abort();
4880 UNREACHABLE();
4881 return NULL;
4882}
4883
4884
kasper.lund44510672008-07-25 07:37:58 +00004885#ifdef DEBUG
4886// ListNatives is ONLY used by the fuzz-natives.js in debug mode
4887// Exclude the code in release mode.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004888static Object* Runtime_ListNatives(Arguments args) {
4889 ASSERT(args.length() == 1);
4890 HandleScope scope;
4891 Handle<JSArray> result = Factory::NewJSArray(0);
4892 int index = 0;
4893#define ADD_ENTRY(Name, argc) \
4894 { \
4895 HandleScope inner; \
4896 Handle<String> name = \
4897 Factory::NewStringFromAscii(Vector<const char>(#Name, strlen(#Name))); \
4898 Handle<JSArray> pair = Factory::NewJSArray(0); \
4899 SetElement(pair, 0, name); \
4900 SetElement(pair, 1, Handle<Smi>(Smi::FromInt(argc))); \
4901 SetElement(result, index++, pair); \
4902 }
4903 RUNTIME_FUNCTION_LIST(ADD_ENTRY)
4904#undef ADD_ENTRY
4905 return *result;
4906}
kasper.lund44510672008-07-25 07:37:58 +00004907#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00004908
4909
4910static Object* Runtime_IS_VAR(Arguments args) {
4911 UNREACHABLE(); // implemented as macro in the parser
4912 return NULL;
4913}
4914
4915
4916// ----------------------------------------------------------------------------
4917// Implementation of Runtime
4918
4919#define F(name, nargs) \
4920 { #name, "RuntimeStub_" #name, FUNCTION_ADDR(Runtime_##name), nargs, \
4921 static_cast<int>(Runtime::k##name) },
4922
4923static Runtime::Function Runtime_functions[] = {
4924 RUNTIME_FUNCTION_LIST(F)
4925 { NULL, NULL, NULL, 0, -1 }
4926};
4927
4928#undef F
4929
4930
4931Runtime::Function* Runtime::FunctionForId(FunctionId fid) {
4932 ASSERT(0 <= fid && fid < kNofFunctions);
4933 return &Runtime_functions[fid];
4934}
4935
4936
4937Runtime::Function* Runtime::FunctionForName(const char* name) {
4938 for (Function* f = Runtime_functions; f->name != NULL; f++) {
4939 if (strcmp(f->name, name) == 0) {
4940 return f;
4941 }
4942 }
4943 return NULL;
4944}
4945
4946
4947void Runtime::PerformGC(Object* result) {
4948 Failure* failure = Failure::cast(result);
4949 // Try to do a garbage collection; ignore it if it fails. The C
4950 // entry stub will throw an out-of-memory exception in that case.
4951 Heap::CollectGarbage(failure->requested(), failure->allocation_space());
4952}
4953
4954
4955} } // namespace v8::internal