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